我刚读过这篇文章:The Truth About Garbage Collection
在“A.3.3 Invisible”部分中,解释了对象如何以及何时进入invisible
状态。
在下面的代码中,分配给变量foo
的对象在离开invisible
块后将变为try/catch
,并且在run
方法退出之前将一直强烈引用(这将永远不会发生,因为while
循环永远运行。
public void run() {
try {
Object foo = new Object();
foo.doSomething();
} catch (Exception e) {
// whatever
}
while (true) { // do stuff } // loop forever
}
本文说明:
但是,JVM的有效实现不可能为零 超出范围时的参考。
为什么效率不高?
我尝试解释如下:
假设此方法的堆栈包含四个元素,现在不可见的对象位于底部
如果你想立即收集对象,你必须弹出并存储三个元素,弹出并丢弃第四个元素,然后将三个仍然有效的元素推回堆栈。
如果在控制流离开run
方法后收集不可见对象,则VM可以简单地弹出所有四个元素并丢弃它们。
答案 0 :(得分:3)
局部变量不在操作数堆栈上,而是在激活帧的局部变量区域中,在通过aload
和astore
字节码引用并将局部变量归零的情况下访问不涉及任何推动和弹出。
归零是低效的,因为它不需要:
修改强>
对最后一项声明的一些评论。
实际上,在字节码级别没有作用域,并且局部变量槽可以保留为根集的一部分,直到该方法返回。当然,JVM实现可以确定局部变量槽何时死亡(即方法返回的所有可能路径都不访问变量或存储)并且不认为它是根集的一部分,但它是绝不需要这样做。
答案 1 :(得分:0)
非常简单的答案是b / c效率低下。
有许多垃圾收集器算法,有些可能会积极收集。有些编译器会在堆栈上进行分配,但在您的情况下最明显的是:doSomething()
实际上可能会在其他地方保留(泄漏)对象的引用。