Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a PhantomReference being in a ReferenceQueue stop the PhantomReference from being GC'd?

Tags:

java

I'm using the LWJGL libraries and unfortunately I need to free up texture/vbo buffers myself whenever a node in my scene graph needs to die, I can't even use finalize() method to do this as I can't guarantee that it will be executed in the same thread the opengl libs expects it to.

So I'm using PhantomReferences. In my scene graph nodes I've put this in the constructor:

phantomReference = new ScenePhantomReference(this, Game.phantomReferenceQueue);
Game.phantomReferenceList.add(phantomReference);

As you can see in the second line I've added the phantomReference to a list in the main class. My logic is that when the node becomes dereferenced the phantomReference won't get garbage collected with it as there's still a reference in the main class.

Is adding it to a list like this needed? Or will it be spared from the GC (maybe the Game.phantomReferenceQueue keeps a reference to it?).

This one is a pain to test, I could just remove the list but the GC could just be processing the object that's being watched before the phantomReference and make it look like the list is redundant, when it really isn't. I'd be paranoid that any different VM implementation or version might decide to do it the other way round.

like image 487
Callum Avatar asked Mar 02 '11 22:03

Callum


1 Answers

Disclaimer: I have not ever used PhantomReference.

However, I did read this article and this javadoc page, and so

  1. "Is adding it to a list like this needed? [...] (maybe the Game.phantomReferenceQueue keeps a reference to it?)": As per the javadoc page: "Reference queues, to which registered reference objects are appended by the garbage collector after the appropriate reachability changes are detected.". So I believe that no, you shouldn't add it the List, since the Queue will automatically have it added by the garbage collector.
  2. I think you have to rephrase a little bit your question - I don't understand what the List is for, i.e. I don't understand the last paragraph. But if you're using the list in order to know if the phantomReference is gc'ed then no, you should not be using the list at all, that's what the ReferenceQueue is there for. Moreover, the List will prevent the phantomReference from being gc'ed!

Edit: Read the title of your post again. To answer the title question by itself: No, because a PhantomReference enters the ReferenceQueue after it has been gc'ed - so by definition it cannot be stopped from being gc'ed. To quote the first link: "The only use for such a reference [note: he means PhantomReference] is keeping track of when it gets enqueued into a ReferenceQueue, as at that point you know the object to which it pointed is dead"

Edit #2: I also think your code is wrong in that you should be initialising the phantom reference as follows (see a simple example here):

PhantomReference scenePhantomRef = new PhantomReference(scene, phantomQueue);

where scene is the ScenePhantomReference from your code (i.e. you should refactor your code so that ScenePhantomReference is name e.g. Scene, you instantiate it as scene and then use the line above to get a handle on a PhantomReference for that object).

like image 100
Lucas Zamboulis Avatar answered Oct 26 '22 03:10

Lucas Zamboulis