我正在阅读《CLR via C#》,据此例子,被最初分配给“obj”的对象将在执行第一行之后,而不是第二行之后,有资格进行垃圾回收。
void Foo()
{
Object obj = new Object();
obj = null;
}
这是因为局部变量的生命周期不是由其定义的作用域决定的,而是由你最后一次读取它的时间决定的。
那么我的问题是:Java又是怎样的呢? 我写了一个程序来检查这种行为,看起来对象仍然存活着。我不认为JVM能够在解释字节码时限制变量的生命周期,所以我尝试使用“java -Xcomp”运行程序来强制进行方法编译,但无论如何,“finalize”都没有被调用。看起来这对Java不成立,但我希望我能在这里得到更准确的答案。另外,Android的Dalvik VM又是怎样的呢?
class TestProgram {
public static void main(String[] args) {
TestProgram ref = new TestProgram();
System.gc();
}
@Override
protected void finalize() {
System.out.println("finalized");
}
}
新增: Jeffrey Richter 在《CLR via C#》一书中提供了代码示例,例如:
public static void Main (string[] args)
{
var timer = new Timer(TimerCallback, null, 0, 1000); // call every second
Console.ReadLine();
}
public static void TimerCallback(Object o)
{
Console.WriteLine("Callback!");
GC.Collect();
}
如果项目的目标是'Release',则在MS .Net上TimerCallback仅调用一次(在GC.Collect()调用后计时器被销毁),如果目标为'Debug',则每秒钟调用一次(变量生命周期增加,因为程序员可以尝试使用调试器访问对象)。但是在Mono上,无论你如何编译,回调都会每秒钟调用一次。看起来Mono的'Timer'实现在线程池中某个地方存储了对实例的引用。而MS的实现则不这样做。