PhantomReference with null queue
Asked Answered
G

1

5

Java allow to write:

new PhantomReference(new Object(), null)

At this case new Object() will be collected?

As I understand, phantom reference is alternative of finalize() method usage.

And after appearing reference in queue, I need to do some additional actions and then run clear()

java doc stays:

It is possible to create a phantom reference with a null queue, but such a reference is completely useless: Its get method will always return null and, since it does not have a queue, it will never be enqueued

What does mean if it will never be enqueued?

As I understand it means that after finalize method invocation rerference will not be added to the referenceQueue. Thus it may lead to:
1. object memory will be cleared at once
2. Object memory will not be cleared

which case correct?

Goddard answered 30/12, 2016 at 12:10 Comment(18)
What is your actual question here? Can you explain your problem more clearly?Spat
Have you looked at this #1599569 for example?Echols
And the javadoc for that PhantomReference ctor clearly says: It is possible to create a phantom reference with a null queue, but such a reference is completely useless: Its get method will always return null and, since it does not have a queue, it will never be enqueued. So, yes, that newly created Object is thus subject to garbage collection.Echols
@GhostCat, Why do you think so? how can we check this? I don't see causal relationshipGoddard
Passing that newly created object X into a PhantomReference ... should not make X a "live" object. There is no reason why the GC should be prevented from collecting it. And as the PhantomReference doesnt have a queue for X either ... I assume the only thing that can happen to X is: being garbage collected the next time the GC runs. And I agree with UNIQUEorn - no idea where you want to go with this question. What is the problem you intend to solve?Echols
@Echols but if we pass queue to constructor, queue hold the reference and it prevent for object to be collected?Goddard
Not at all. The links clearly explain that: PhantomRefernces do not prevent gargabe collection. They are simply a mechanism to understand when the GC does its work. You can say: "give me a shoulder tap when X goes away". And then you get a shoulder tap; and decide what to do about that. Thats it.Echols
@Echols looks like it is correct for weak/soft references nut incorect for phantom referenceGoddard
And what makes you think so?Echols
@Echols docs.oracle.com/javase/7/docs/api/java/lang/ref/…Goddard
@Echols Unlike soft and weak references, phantom references are not automatically cleared by the garbage collector as they are enqueued. An object that is reachable via phantom references will remain so until all such references are cleared or themselves become unreachable.Goddard
@UNIQUEorn, I merely learn/investigate java deeperGoddard
ibm.com/developerworks/library/j-refsGoddard
@gstackoverflow: that IBM article contradicts the documentation and actual implementation behavior of Oracle’s JRE in several aspects. Don’t count on it…Interlace
@gstackoverflow: I noted that you have several gc related questions that are still open, i.e. q1, q2, q3 and q4. So it would be great to know whether there are still things unclear or whether these issues aren’t relevant to you anymore. I’m thinking about adding an answer here, especially as it might contradict the most of the comments, but if you don’t need it anymore, you may remove the question instead.Interlace
@Interlace I will be happy if you answer these questionsGoddard
@gstackoverflow: the other questions have answers, two of them even have an answer of mine. If they are not satisfying, you should add clarifying comments to address what’s missing. Otherwise, you may accept an answer (doesn’t need to be mine ;-). I added an answer to this question; it became a bit bigger than I thought, but that’s a really interesting topic…Interlace
@Interlace I will see all answers tomorrow.Goddard
I
9

Well, as you noticed yourself, a PhantomReference is not automatically cleared. This implies that as long as you keep a strong reference to the PhantomReference, the referent will stay phantom reachable. As the documentation says: “An object that is reachable via phantom references will remain so until all such references are cleared or themselves become unreachable.

However, considering when an object is unreachable (now I’m talking about the “phantom references themselves”) can lead to many surprises. Especially as it’s very likely that the reference object, not providing useful operations, will not be subsequently touched anymore.

Since the PhantomReference without a queue will never be enqueued and its get() method will always return null, it is indeed not useful.

So why does the constructor allows to construct such a useless object? Well, the documentation of the very first version (1.2) states that it will throw a NullPointerException if the queue is null. This statement persists until 1.4, then Java 5 is the first version containing the statement that you can construct a PhantomReference without a queue, despite being useless. My guess is, that it always inherited the super class’ behavior of allowing a null queue, contradicting the documentation, and it was noticed so late, that the decision was made to stay compatible and adapt the documentation rather than changing the behavior.


The question, even harder to answer, is why a PhantomReference isn’t automatically cleared. The documentation only says that a phantom reachable object will remain so, which is the consequence of not being cleared, but doesn’t explain why this has any relevance.

This question has been brought up on SO, but the answer isn’t really satisfying. It says “to allow performing cleanup before an object is garbage collected”, which might even match the mindset of whoever made that design decision, but since the cleanup code can’t access the object, it has no relevance whether it is executed before or after the object is reclaimed. As said above, since this rule depends on the reachability of the PhantomReference object, which is subject to optimizing code transformations, it might be even the case that the object is reclaimed together with the PhantomReference instance before the cleanup code completes, without anyone noticing.

I also found a similar question on the HotSpot developer mailing list back in 2013 which also lacks an answer.

There is the enhancement request JDK-8071507 to change that behavior and clear PhantomReferences just like the others, which has the status “fixed” for Java 9, and indeed, its documentation now states that they are cleared like any other reference.

This, unfortunately implies that the answer at the beginning of my post will be wrong starting with Java 9. Then, new PhantomReference(new Object(), null) will make the newly created Object instance immediately eligible for garbage collection, regardless of whether you keep a strong reference to the PhantomReference instance or not.

Interlace answered 1/2, 2017 at 19:2 Comment(2)
nice research. Thus since java 9 PhantomReference will not finalize alternative (because semantic "before clearing") will be violated ? what about back compatibility?Goddard
As I tried to say, the “before clearing” semantic never had any use. The phantom reference never allows accessing the referent, hence, it doesn’t matter whether the referent still exists in memory or not. Keeping it in memory longer than necessary was a waste of resources. That’s why several applications (including mine) always used WeakReference instead, which eliminates the need to collect the referent twice, thus being potentially more efficient. For objects without a custom finalize() method, there is no semantic difference. Starting with Java 9, the differences are even less.Interlace

© 2022 - 2024 — McMap. All rights reserved.