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?
source to share
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.
source to share