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 的正确用法是什么,以免发生这种情况?

最佳答案

一旦您不再拥有对该对象的强引用,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.

10-08 16:28