The java
command manual entry provides conclusive proof that System.gc()
is not guaranteed to cause a garbage collection. In the "Advanced Garbage Collection Options" section, it describes this option:
-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.
When the javadoc for System.gc()
talks about a "best effort", that can mean "no effort at all".
You say:
I don't understand why checking if a weak referenced object have been garbaged is not a proof ?
Your "proof" is based on a fallacy, best illustrated by this:
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?
And there is another reason why your example may behave differently on different JVMs.
When you assign null
to obj
, nothing in the remainder of the method's scope reads that variable. The compiler is therefore allowed to optimize away the assignment. As JLS 17.4 says:
"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."
If the assignment is optimized away, then the GC could see the previous non-null value in the variable, treat the object is still reachable, and not break the WeakReference
.
I cannot tell you if there is a Java implementation that would behave like that, but I would argue that 1) the JLS permits that, and 2) it is a plausible optimization for a JIT compiler to perform.