为什么此代码不能确保已完成完整的垃圾收集?
Why this code does not ensure that a full garbage collection has been done?
在previous answer on forcing garbage collection, @shams proposes this method from 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 中不同意此方法 保证完成垃圾收集的事实 。
我不明白为什么检查弱引用对象是否已被垃圾化不是证明?
作为开发人员,您不能强迫垃圾收集器 运行,您所能做的就是请求它。 JVM 将决定它是否 运行s.
对此你无能为力。
如上所述,java 垃圾收集不能强制...但可以帮助。
这么好的 java 代码在完成时总是将变量设为 null,因为将变量设为 null 的行为会引起垃圾收集器的兴趣。
同样弱引用比其他引用更容易被垃圾收集器维护,这本质上就是弱引用的目的。你必须记住,如果只有定义 class 本身有对它的引用,就会收集弱引用。这意味着您不能使用弱引用来替代普通引用。
管理垃圾回收的艺术是一个大课题,它在 Java 的实现之间有所不同。例如,Android java 比 Oracle java 更积极地进行垃圾收集。
The java
command manual entry 提供 确凿证据 System.gc()
不保证会导致垃圾收集。在“高级垃圾收集选项”部分,它描述了这个选项:
-XX:+DisableExplicitGC
Enables the option that disables processing of calls to System.gc()
. This option is disabled by default, meaning that calls to System.gc()
are processed. If processing of calls to System.gc()
is disabled, the JVM still performs GC when necessary.
当 System.gc()
的 javadoc 谈到“尽力而为”时,这可能意味着“完全不努力”。
你说:
I don't understand why checking if a weak referenced object have been garbaged is not a proof ?
你的“证明”是基于一个谬论,最好的说明是:
Today I painted my letterbox and my kitten died.
Can I logically conclude that every time I paint my letterbox, a kitten will die?
Does it also apply if someone else paints a letterbox? Or if I paint my front gate?
还有另一个原因导致您的示例在不同的 JVM 上可能表现不同。
当您将 null
赋值给 obj
时,该方法范围的其余部分不会读取该变量。因此,编译器 允许 优化赋值。正如 JLS 17.4 所说:
"The memory model describes possible behaviors of a program. An implementation is free to produce any code it likes, as long as all resulting executions of a program produce a result that can be predicted by the memory model."
"This provides a great deal of freedom for the implementor to perform a myriad of code transformations, including the reordering of actions and removal of unnecessary synchronization."
如果分配被优化掉,那么 GC 可以看到变量中以前的非空值,认为对象仍然可以访问,并且不会破坏 WeakReference
.
我无法告诉您是否有一个 Java 实现会表现得像那样,但我认为 1) JLS 允许这样做,以及 2) 它是 JIT 编译器的合理优化执行。
I don't understand why checking if a weak referenced object have been garbaged is not a proof ?
除了其他人根据规范指出的原因之外,还有一个简单的问题,即您正在尝试测试 full GC。弱引用可能会在新生代收集过程中被剔除。
使用基于区域的 GC,例如 G1 部分老年代 GC 也是可能的。
并且对于像 Azul 的 C4 这样的完全并发的 GC,"full GC" 的概念甚至可能不存在。
最重要的是,即使是一次完整的 GC 传递也可能不是 "complete",因为 reference/finalizer 队列可能用于在某些对象被回收后延迟处理其他对象,即根据程序逻辑释放所有内容,可能需要多次 GC 传递和引用队列处理步骤。
这在基于引用队列的本机资源处理的情况下非常重要。
在previous answer on forcing garbage collection, @shams proposes this method from 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 中不同意此方法 保证完成垃圾收集的事实 。
我不明白为什么检查弱引用对象是否已被垃圾化不是证明?
作为开发人员,您不能强迫垃圾收集器 运行,您所能做的就是请求它。 JVM 将决定它是否 运行s.
对此你无能为力。
如上所述,java 垃圾收集不能强制...但可以帮助。 这么好的 java 代码在完成时总是将变量设为 null,因为将变量设为 null 的行为会引起垃圾收集器的兴趣。
同样弱引用比其他引用更容易被垃圾收集器维护,这本质上就是弱引用的目的。你必须记住,如果只有定义 class 本身有对它的引用,就会收集弱引用。这意味着您不能使用弱引用来替代普通引用。
管理垃圾回收的艺术是一个大课题,它在 Java 的实现之间有所不同。例如,Android java 比 Oracle java 更积极地进行垃圾收集。
The java
command manual entry 提供 确凿证据 System.gc()
不保证会导致垃圾收集。在“高级垃圾收集选项”部分,它描述了这个选项:
-XX:+DisableExplicitGC
Enables the option that disables processing of calls to
System.gc()
. This option is disabled by default, meaning that calls toSystem.gc()
are processed. If processing of calls toSystem.gc()
is disabled, the JVM still performs GC when necessary.
当 System.gc()
的 javadoc 谈到“尽力而为”时,这可能意味着“完全不努力”。
你说:
I don't understand why checking if a weak referenced object have been garbaged is not a proof ?
你的“证明”是基于一个谬论,最好的说明是:
Today I painted my letterbox and my kitten died.
Can I logically conclude that every time I paint my letterbox, a kitten will die?
Does it also apply if someone else paints a letterbox? Or if I paint my front gate?
还有另一个原因导致您的示例在不同的 JVM 上可能表现不同。
当您将 null
赋值给 obj
时,该方法范围的其余部分不会读取该变量。因此,编译器 允许 优化赋值。正如 JLS 17.4 所说:
"The memory model describes possible behaviors of a program. An implementation is free to produce any code it likes, as long as all resulting executions of a program produce a result that can be predicted by the memory model."
"This provides a great deal of freedom for the implementor to perform a myriad of code transformations, including the reordering of actions and removal of unnecessary synchronization."
如果分配被优化掉,那么 GC 可以看到变量中以前的非空值,认为对象仍然可以访问,并且不会破坏 WeakReference
.
我无法告诉您是否有一个 Java 实现会表现得像那样,但我认为 1) JLS 允许这样做,以及 2) 它是 JIT 编译器的合理优化执行。
I don't understand why checking if a weak referenced object have been garbaged is not a proof ?
除了其他人根据规范指出的原因之外,还有一个简单的问题,即您正在尝试测试 full GC。弱引用可能会在新生代收集过程中被剔除。
使用基于区域的 GC,例如 G1 部分老年代 GC 也是可能的。
并且对于像 Azul 的 C4 这样的完全并发的 GC,"full GC" 的概念甚至可能不存在。
最重要的是,即使是一次完整的 GC 传递也可能不是 "complete",因为 reference/finalizer 队列可能用于在某些对象被回收后延迟处理其他对象,即根据程序逻辑释放所有内容,可能需要多次 GC 传递和引用队列处理步骤。 这在基于引用队列的本机资源处理的情况下非常重要。