Reputation: 1100
As you can see in the first block SAVE_HOOK = null;
before going inside the if branch, I think SAVE_HOOK == null
, so it should not go into SAVE_HOOK.isAlive();
. But actually, I test it in the Eclipse
:
Eclipse IDE for Java Developers
Version: Neon.3 Release (4.6.3)
Build id: 20170314-1500
Why does this happen?
public class FinalizeEscapeGC {
public static FinalizeEscapeGC SAVE_HOOK = null;
public void isAlive() {
System.out.println("yes, i am still alive :)");
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize mehtod executed!");
FinalizeEscapeGC.SAVE_HOOK = this;
}
public static void main(String[] args) throws Throwable {
SAVE_HOOK = new FinalizeEscapeGC();
// ---------------block 1----------------//
SAVE_HOOK = null;
System.gc();
Thread.sleep(500);
if (SAVE_HOOK != null) { // "SAVE_HOOK = null;"
SAVE_HOOK.isAlive(); // why the frist time it can go inside this if branch?
} else {
System.out.println("no, i am dead :(");
}
// ---------------block 1----------------//
// the same as the above block
// ---------------block 2----------------//
SAVE_HOOK = null;
System.gc();
Thread.sleep(500);
if (SAVE_HOOK != null) {
SAVE_HOOK.isAlive();
} else {
System.out.println("no, i am dead :(");
}
// ---------------block 2----------------//
}
}
Result:
finalize mehtod executed!
yes, i am still alive :)
no, i am dead :(
Upvotes: 1
Views: 304
Reputation: 50776
It sounds like you're trying to ask two questions:
SAVE_HOOK
not null after the first block?The simple answer to the first question is: Because System.gc()
triggered the garbage collector, which in turn ran the finalizer, which explicitly reassigns the reference. But I assume you know that already, and what you mean to ask is: Why wasn't the object reclaimed after the finalizer completed?
The answer is in the documentation to finalize()
:
After the
finalize
method has been invoked for an object, no further action is taken until the Java virtual machine has again determined that there is no longer any means by which this object can be accessed [...] at which point the object may be discarded.
So as long as you still have a strong reference to the object, it will never be garbage collected.
The answer to the second question is: You set it to null and it's never reassigned because the finalizer for a particular instance will only ever run once. This is also in the documentation, right after the previous quote:
The
finalize
method is never invoked more than once by a Java virtual machine for any given object.
Upvotes: 1
Reputation: 23
In an object's life lifecycle, it will go through reachable->finalizable->finalized->reclaimed phases. After finalize() method was execute, the object will get in finalized phase, and wait for the next gc trigger, it will be reclaimed. So in the lifecycle, the finalize() method will be exectued only once. Your SAVE_HOOK is a static variable and it was assigned value in finalize() method again. That's why in first if block, it's not null. but the second time, it's dead.
Upvotes: 0
Reputation: 719626
It boils down to this: an object can only be finalized once in its lifetime. The finalize method can cause the object to escape deletion the first time, but next time the object is detected as unreachable, it will simply be deleted.
Upvotes: 1