在previous answer forcing garbage collection上,@shams从jslibs提出此方法:
/**
* This method guarantees that garbage collection is done unlike <code>{@link System#gc()}</code>
*/
public static void gc() {
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
obj = null;
while (ref.get() != null) {
System.gc();
}
}
但在a comment中,@MarkoTopolnik不同意此方法保证垃圾收集完成这一事实。
我不明白为什么检查弱引用对象是否被证实不是证据?
答案 0 :(得分:2)
The java
command manual entry提供确凿证据,System.gc()
无法保证会导致垃圾回收。在&#34;高级垃圾收集选项&#34;部分,它描述了这个选项:
<强> -XX:+ DisableExplicitGC 强>
启用禁用处理
System.gc()
调用的选项。默认情况下禁用此选项,这意味着将处理对System.gc()
的调用。如果禁用了对System.gc()
的调用的处理,则JVM在必要时仍会执行GC。
当System.gc()
的javadoc谈论&#34;尽力而为&#34;时,这可能意味着&#34;根本没有努力&#34;。
你说:
我不明白为什么检查弱引用对象是否被证实不是证据?
您的&#34;证明&#34;是基于一个谬论,最好的说明:
今天我画了我的信箱,我的小猫就死了。
我可以从逻辑上得出结论,每当我画信箱时,小猫都会死吗?
如果其他人描绘信箱,它是否也适用?或者如果我画前门?
还有另一个原因可能导致您的示例在不同的JVM上表现不同。
当您将null
分配给obj
时,方法范围的其余部分中的任何内容都不会读取该变量。因此,编译器允许来优化分配。正如JLS 17.4所说:
&#34;内存模型描述了程序的可能行为。一个实现可以自由地生成它喜欢的任何代码,只要程序的所有结果执行产生一个可以由内存模型预测的结果。&#34;
&#34;这为实现者提供了大量的自由来执行无数的代码转换,包括重新排序操作和删除不必要的同步。&#34;
如果分配被优化掉,那么GC可以看到变量中的先前非空值,处理对象仍然可以访问,并且不会破坏WeakReference
。
我不能告诉你是否有一个类似的Java实现,但我认为1)JLS允许这样做,2)它是JIT编译器执行的合理优化。
答案 1 :(得分:1)
如上所述,java垃圾收集不能强制...但它可以帮助。 如此好的java代码在它们完成时总是为null变量,因为归零变量的行为引起了垃圾收集器的兴趣。
类似的弱引用由垃圾收集器维护得比其他引用更紧密,这本质上是弱引用的目的。您必须记住,如果只有定义类本身具有对它的引用,则会收集弱引用。这意味着你不能使用弱引用来代替普通引用。
管理垃圾收集的技术是一个很大的主题,它在Java的实现之间有所不同。例如,Android java比Oracle java更积极地收集垃圾。
答案 2 :(得分:1)
我不明白为什么检查一个弱引用对象是否已被证实?
除了基于规范的其他人指出的原因之外,还有一个简单的问题,即您正在尝试测试完整GC 。在年轻一代的收藏中可能会剔除弱参考。
对于像G1这样的基于区域的GC,部分老一代的GC也是可能的。
对于完全并发的GC,如Azul的C4,“完整GC”的概念甚至可能不存在。
最重要的是,即使单个完整的GC传递可能也不是“完整的”,因为一旦某个对象被回收,可能会使用引用/终结器队列来懒惰地处理其他对象,即多个GC传递并且可能需要参考队列处理步骤,这取决于程序逻辑以释放所有内容。 在基于引用队列的本机资源处理的情况下,这可能非常重要。
答案 3 :(得分:0)
作为开发人员,您无法强制垃圾收集器运行,您可以做的就是请求它。 JVM将决定它是否运行。
你无能为力。