Java / Scala对垃圾收集有什么保证?

时间:2014-09-07 21:39:06

标签: java scala garbage-collection playframework-2.3

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

2 个答案:

答案 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()调用之前发生结束。