【发布时间】:2012-01-11 17:13:15
【问题描述】:
我正在阅读“通过 C# 进行 CLR”,似乎在此示例中,最初分配给“obj”的对象将在执行第 1 行而不是第 2 行之后有资格进行垃圾回收。
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”(在 GC.Collect() 调用后计时器被销毁),TimerCallback 在 MS .Net 上仅调用一次,如果目标是“调试”,则每秒调用一次(变量寿命增加,因为程序员可以尝试访问带有调试器的对象)。但是无论您如何编译它,都会每秒调用 Mono 回调。看起来 Mono 的“计时器”实现在线程池中的某处存储了对实例的引用。 MS 实现不这样做。
【问题讨论】:
-
我之前在 Java 规范中找不到这个。请注意,.NET 可能比您预期的更疯狂 - 如果 CLR 知道不会再引用更多实例变量,那么在执行实例方法时可能会收集实例。
标签: c# java android .net garbage-collection