Javadoc 8 for PhantomReference says:
Phantom links are most often used to schedule pre-mortem cleanup actions in a more flexible way than is possible with the Java termination mechanism.
So, I tried to create a thread that calls the close() method of the test object, which has the right to garbage collection. run() tries to get all test objects before opening .
In fact, the resulting test objects are all null . The expected behavior is that test objects are retrieved and the close method is called.
No matter how many test objects you create, there is not a single test object that you can catch pre-mortem (you need to increase the timeouts and call the GC several times).
What am I doing wrong? Is this a Java bug?
Managed Test Code:
I tried to create an example of Minimal, Complete and Verifiable, but it is still quite long. I am using java version "1.8.0_121" 32-bit in 64-bit version of Windows 7.
public class TestPhantomReference { public static void main(String[] args) throws InterruptedException { // Create AutoClose Thread and start it AutoCloseThread thread = new AutoCloseThread(); thread.start(); // Add 10 Test Objects to the AutoClose Thread // Test Objects are directly eligible for GC for (int i = 0; i < 2; i++) { thread.addObject(new Test()); } // Sleep 1 Second, run GC, sleep 1 Second, interrupt AutoCLose Thread Thread.sleep(1000); System.out.println("System.gc()"); System.gc(); Thread.sleep(1000); thread.interrupt(); } public static class Test { public void close() { System.out.println("close()"); } } public static class AutoCloseThread extends Thread { private ReferenceQueue<Test> mReferenceQueue = new ReferenceQueue<>(); private Stack<PhantomReference<Test>> mPhantomStack = new Stack<>(); public void addObject(Test pTest) { // Create PhantomReference for Test Object with Reference Queue, add Reference to Stack mPhantomStack.push(new PhantomReference<Test>(pTest, mReferenceQueue)); } @Override public void run() { try { while (true) { // Get PhantomReference from ReferenceQueue and get the Test Object inside Test testObj = mReferenceQueue.remove().get(); if (null != testObj) { System.out.println("Test Obj call close()"); testObj.close(); } else { System.out.println("Test Obj is null"); } } } catch (InterruptedException e) { System.out.println("Thread Interrupted"); } } } }
Expected Result:
System.gc() Test Obj call close() close() Test Obj call close() close() Thread Interrupted
Actual output:
System.gc() Test Obj is null Test Obj is null Thread Interrupted
java garbage-collection finalizer finalize phantom-reference
notes-jj Apr 09 '17 at 20:54 on 2017-04-09 20:54
source share