'Java PhantomReference vs finalize()

I've been reading this article about PhantomReference https://www.baeldung.com/java-phantom-reference and simplified sample code found there:

public static void main(String[] args) throws InterruptedException {
    ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
    Object object = new Object();
    PhantomReference<Object> phantomReference = new PhantomReference<>(object, referenceQueue);
    object = null;
    System.gc();
    Thread.sleep(1_000);
    System.out.println("isEnqueued() after GC: " + phantomReference.isEnqueued());
    Reference reference = referenceQueue.poll();
    if(reference != null) {
        System.out.println("isEnqueued() after poll(): " + phantomReference.isEnqueued());
    }
}

Here is output:

isEnqueued() after GC: true
isEnqueued() after poll(): false

So everything is working as expected, strong reference to object is set to null which is detected by GC and phantom reference is added to the queue.

Now in that article they say: "The Garbage Collector adds a phantom reference to a reference queue after the finalize method of its referent is executed. It implies that the instance is still in the memory."

So I wanted to make a test and override finalize method like:

Object object = new Object() {
    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalize()");
    }
};

But then output is different, phantom reference is not added to the queue anymore:

finalize()
isEnqueued() after GC: false

Could somebody explain why after this change output is different and how to change this code so phantom reference would be added to queue?

I've been testing this on JDK 8 and 11, same results on both platforms.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source