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

Pau*_*per 4 java garbage-collection scala playframework-2.3

Play框架具有play.api.libs.Files.TemporaryFile对a的引用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()
  }

}
Run Code Online (Sandbox Code Playgroud)

我知道这有一些问题,例如,你可以填满整个磁盘,而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()
    }
}
Run Code Online (Sandbox Code Playgroud)

在我从文件中读取之前可以删除/ 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()
  }
}
Run Code Online (Sandbox Code Playgroud)

如果在上面的示例中,tempFile可能在我使用它之前将其删除,那么正确使用的是什么,TemporaryFile以免发生这种情况?

jdp*_*nix 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()
    }
}
Run Code Online (Sandbox Code Playgroud)

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()
  }
}
Run Code Online (Sandbox Code Playgroud)

结果是一样的.

在一个小变体(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. 
Run Code Online (Sandbox Code Playgroud)