Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the state of a weak reference that has been manually enqueued?

What's the state of an object when you manually enqueue a reference?

this.s = "foo";
WeakReference<String> wr = new WeakReference<String>(this.s);
wr.enqueue();

All the documentation I've found talks about the garbage collector enqueueing the object, not about what happens when you do it manually.

And is there any situation where this would make sense? What does it mean for an object to be enqueued, but to still have reachable references (strong, weak, phantom)?

Edit: extra bonus followup question: does the object get enqueued again when it becomes unreachable some time in the distant future?

like image 510
James Moore Avatar asked Apr 07 '11 18:04

James Moore


2 Answers

The strong reference would remain, so the object is not eligible for collection. As JVestry points out, if you create the weak reference with a queue, then wr.enqueue() returns true as expected.

A potential use for this would be to have your handler be able to operate on an object subject to either its pending garbage collection or some other system state change where you would want to take the same action as if the object were being collected, e.g. maybe you keep a soft reference to something that holds system resources so that the system can handle a low memory situation while you are still able to manage closing the resources yourself if you finish normally.

On the second question, a reference is only enqueued once, whether you do it with enqueue() or the gc does it for as a part of a collection.

EDIT It is important to remember that the relationship between the referencequeue is to the reference, in this case wr, and not the referent, in this case s. You could have multiple weak references to the same object and achieve multiple enqueues (sort of), one for each weak reference. But, it is the weak reference that is in the queue, not the referent, although it ought to still be reachable from the weak reference. See javadoc on java.lang.ref in the Notification section for more details.

like image 187
philwb Avatar answered Oct 24 '22 12:10

philwb


There is a good article about types of references in Java: http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html

In few words: You can do something like this:

public class Main {
    public static void main(String[] args) throws InterruptedException{
        String weakString = "Help me";
        ReferenceQueue<String> refQ = new ReferenceQueue<String>();
        WeakReference<String> weakRef = new WeakReference<String>(weakString, refQ);
        //there is no more "hard reference to the string"
        weakString = null;
        //there is no object in ReferenceQueue
        System.out.println(refQ.poll());
        //put the object in the ReferenceQueue
        weakRef.enqueue();
        while (true) {
            //There will be returned "Help me" until the garbage collector will "kill" 
            //"weak" string. This will be done after some time because there are no                                     
            //more strong references to the string. After that will be returned a null  
            //object.
            System.out.println(weakRef.get());
            //only one time there will be returned a refenrece to the String object
            System.out.println(refQ.poll());
            Thread.sleep(1000);
        }
    }
}

This is designed for working with some kind of cache. In this way you can be sure that there won't be non-used object in the memory for long time. The ReferenceQueue could be used for performing some kind of cleanup after calling weakRef.enqueue();. For example closing files or streams that was used to work with data.

like image 23
StKiller Avatar answered Oct 24 '22 14:10

StKiller