Play框架有play.api.libs.Files.TemporaryFile
,其中包含File
的引用,并在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()
}
}
我知道这有一些问题,例如,你可以填满整个磁盘而JVM不需要GC。
但是我在这里询问"正确性"一个程序,即一个没有磁盘空间限制的程序。
def foo() {
val tempFile = TemporaryFile(new File("/tmp/foo"))
val inputStream = new FileInputStream(tempFile.file) // last use
try {
println(inputStream.read())
} finally {
inputStream.close()
}
}
在我从文件中读取之前,/ foo / bar会被删除吗?我在tempFile
之后没有使用// last use
,那么可以在此之后立即确定吗?
或者如果它作为参数传递给函数呢?
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()
}
}
如果在上面的示例中,tempFile
可能会在我使用它之前被移除,TemporaryFile
的正确用法是什么,以免发生这种情况?
答案 0 :(得分:5)
一旦您不再具有对该对象的强引用,Java对象就有资格进行垃圾回收。这取决于您是否 使用"对象与否。
在此示例中,
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
没有资格进行垃圾回收,因此不再使用foo()
之前的终结。使用来自tempFile
的成员的对象可能会使用它,并且使其保持不合格的时间长于foo()
内的最后一次使用。
在此示例中,
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()
}
}
结果是一样的。
在一个小变体(Java,我不太了解Scala语法),
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.
答案 1 :(得分:2)
在执行退出其范围之前,不会最终确定局部变量。 GC没有最终确定你不使用的对象,它最终确定了你不能再访问的对象,所以在你的tempFile示例中,它不会在foo()调用之前发生结束。