Reputation: 21
I am leaning phantom reference ,and I got confused how is a phantom reference enqueued when the referent is being garbage-collected.
Here is my code
Object s = new Object();
ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
PhantomReference<Object> ref = new PhantomReference<Object>(s, queue);
s = null;
System.gc();
TimeUnit.SECONDS.sleep(1);
System.out.println(queue.poll());
As expected, queue.poll will return the phantom reference :ref.
But if I make a little change of the code : remove the local variable "ref", queue.poll will return null.
So I can infer that, when JVM tries to garbage collect an object ,it will check all the reference to see if there was any that can reach the object.
This should be a very slow progress.?
I designed a program: use phantom reference to trace resource leak. When resource is allocated, a phantom reference is new and bind to the resource.Then I found that:all the phantom references must be stored ,otherwise the phantom reference will not enqueue.
And I checked the netty code ,found that ,netty stores all the phantom references :io.netty.util.ResourceLeakDetector#allLeaks.
Upvotes: 2
Views: 490
Reputation: 298469
As the specification states, “If a registered reference becomes unreachable itself, then it will never be enqueued”. This, however, should not come at a surprise, as without a reachable reference object that defines a special reachability state, there is no special reachability state. All that the specification makes clear, is, that as long as a reference object has not been enqueued, there is no reference from the queue to the reference object.
So I can infer that, when JVM tries to garbage collect an object ,it will check all the reference to see if there was any that can reach the object.
Besides that the JVM never tries to collect a single object, you have just described what garbage collection is all about, traversing all references to find out which objects are still reachable.
This should be a very slow progress.?
It would be very slow if the garbage collector did this again for every single object. But the garbage collector does a traversal for all objects. Objects not encountered during the traversal are garbage per se, so these unreachable objects do not need any special handling, which includes abandoned reference objects.
Still, garbage collection does, of course, bear an overhead, which is the reason why System.gc()
should not get called unless for debugging like in your example program.
Upvotes: 2
Reputation: 36
The garbage collector treats a reference object like any other object. From the documentation:
If a registered reference becomes unreachable itself, then it will never be enqueued.
In theory, yes, using reference objects will introduce inefficiency to garbage collection, so I would not create a reference object for every application object. But in practice the set of reference objects tends to be very small: they're intended to track resources like database connections, not arbitrary objects.
Upvotes: 1