What guarantees does Java / Scala make about garbage collection?

In a replay structure play.api.libs.Files.TemporaryFile

that contains a link to File

, and removes it in TemporaryFile#finalize()

.

case class TemporaryFile(file: File) {

  def clean(): Boolean = {
    file.delete()
  }

  def moveTo(to: File, replace: Boolean = false) {
    Files.moveFile(file, to, replace = replace)
  }

  override def finalize {
    clean()
  }

}

      

I know there are some problems with this, for example you can fill an entire disk without the JVM feeling the need for GC.


But here I am asking about the "correctness" of the program, i.e. about the program without restrictions on disk space.

def foo() {
    val tempFile = TemporaryFile(new File("/tmp/foo"))

    val inputStream = new FileInputStream(tempFile.file) // last use
    try {
        println(inputStream.read())
    } finally {
        inputStream.close()
    }
}

      

Could / foo / bar get deleted before I read from file? I do not use tempFile

after // last use

, so what can be completed immediately after?

Or what if it is passed as an argument to a function?

def foo() {
  val tempFile = TemporaryFile(new File("/tmp/foo"))
  bar(tempFile)
}

def bar(tempFile: TemporaryFile) {
  val inputStream = new FileInputStream(tempFile.file) // last use
  try {
      println(inputStream.read())
  } finally {
      inputStream.close()
  }
}

      


If in the above example, it tempFile

can be removed before I do it, then what is the correct way to use TemporaryFile

it to prevent this from happening?

+3


source to share


2 answers


Java objects are eligible for garbage collection if you no longer have a reference to the object. It doesn't matter if you are using this object or not.

In this example



def foo() {
    val tempFile = TemporaryFile(new File("/tmp/foo"))

    val inputStream = new FileInputStream(tempFile.file) // last use
    try {
        println(inputStream.read())
    } finally {
        inputStream.close()
    }
}

      

tempFile

is not eligible for garbage collection and therefore completion until foo()

no longer in use. It is possible that objects that use members from tempFile

may and may not use it longer than the last use internally foo()

.

In this example



def foo() {
  val tempFile = TemporaryFile(new File("/tmp/foo"))
  bar(tempFile)
}

def bar(tempFile: TemporaryFile) {
  val inputStream = new FileInputStream(tempFile.file) // last use
  try {
      println(inputStream.read())
  } finally {
      inputStream.close()
  }
}

      

The result is the same.

In a small version (Java, I don't know Scala syntax),

class Foo {
    List<Object> objects = new List<Object>(); 
    void foo(Object o) { 
        objects.add(o); 
    }
}

// ...

Foo f = new Foo(); 
f.foo(new Object()); // The object we just created is not eligible for garbage 
                     // collection until the `Foo f` is not used, because
                     // it holds a strong reference to the object. 

      

+5


source


The local variable will not be completed until the execution completes its work. GC does not terminate objects you are not using, terminates objects that you can no longer access , so in your tempFile example this will not happen before the call to foo () has finished.



+2


source







All Articles