views:

101

answers:

4

I've something like this

 private Map<MyObj1, MyObj2> map = new WeakHashMap<MyObj1, MyObj2>();

 ... somewhere in the code ...
 MyObj1 myObj1 = new MyObj1();
 map.put(myObj1, new MyObj2();
 ...
 myObj1 = null;

... somewhere else in a thread ... (I would like to pass to a checkThis(MyObj2) method the Value associated with the entry that was removed from the Map)
/* something like this maybe */
while (true) {
    MyObj2 myObj2 = referenceQueue.remove().get();
    checkThis(myObj2);
}

MyObj1 key might be removed when GC comes into play and there is no strong reference to it.

I'd like to pass to checkThis(MyObj2) the particular map-value Object associated with the key that was removed (maybe checking a ReferenceQueue?)

I can't figure out how to put this into code

EDIT: Sorry I badly expressed my question... I've change it.

A: 

The real problem about what you want to do is that a WeakHashMap relies on the garbage collector to release unusued items.

Since the GC will do its work whenever it wants without any kind of respect for what you are doing it will be difficult to track changes on the hashmap. Actually what you say

"MyObj1 key is removed when there is no strong reference to it"

is not exact. MyObj1 is free to be released by the GC if it doesn't have strong refs around but if there's no need to release it it simply won't get released.

Jack
you're right Jack, sorry I badly expressed my question
mickthompson
A: 

From the WeakHashMap preamble (italics added):

A hashtable-based Map implementation with weak keys. An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. More precisely, the presence of a mapping for a given key will not prevent the key from being discarded by the garbage collector, that is, made finalizable, finalized, and then reclaimed. When a key has been discarded its entry is effectively removed from the map, so this class behaves somewhat differently from other Map implementations.

However, you are never told by the WeakHashMap when it "loses" an entry :-) If you only care about keys-at-a-particular-instance-in-time then you can use a scan of the map (also only practical for some n). Otherwise, go with your hunch about the ReferenceQueue.

This link may be useful: Java Reference Objects

pst
A: 

Reference queues

Once a WeakReference starts returning null, the object it pointed to has become garbage and the WeakReference object is pretty much useless. This generally means that some sort of cleanup is required; WeakHashMap, for example, has to remove such defunct entries to avoid holding onto an ever-increasing number of dead WeakReferences.

The ReferenceQueue class makes it easy to keep track of dead references. If you pass a ReferenceQueue into a weak reference's constructor, the reference object will be automatically inserted into the reference queue when the object to which it pointed becomes garbage. You can then, at some regular interval, process the ReferenceQueue and perform whatever cleanup is needed for dead references.

See this page for a tutorial on how to use.

Could you please indicate why you are using this ? There are very few valid uses.
i.e. A cache is not a valid use (or at least not a good one)

Edit:

This code is equivalent to using a weakHashMap but you need to explicitly do this to correlate the queue with the map.

HashMap aHashMap = new HashMap();
ReferenceQueue Queue = new ReferenceQueue();
MyWeakReference RefKey = new MyWeakReference(key, Queue);
aHashMap.put(RefKey, value);
Romain Hippeau
Thanks for your response. I'd like to know which was the Value object associated with the Key-Value entry that was removed from a WeakHashMap. A sort of EventListener of the WeakHashMap remove() that will contain a call to something like processRemovedValue(value) (I used checkThis(MyObj2) in my updated question)
mickthompson
@mickthompson You have to keep polling the queue, you will not be notified. I still wonder why you are trying to implement this. If sonebody needs to come behind you then it will be a nightmare for them, this is a very obscure part of the Language/API.
Romain Hippeau
as in my example above I keep polling the queue in a thread.. but even if something is removed from WeakHashMap my thread is always blocked on referenceQueue.remove().get() .. I tried to change my map in Map<WeakReference<MyObj1>, MyObj2> but it didn't work
mickthompson
If you look at the docs for remove it says it will block until one is available. You probably want to do a poll() and if something is there call remove(). You still never answered my question of why you are trying to do this.
Romain Hippeau
I read the docs. I know poll won't block, the point is that I still don't get anything even when something is removed from the WeakHashMap. To respond to your question of what I'm trying to achieve: I have a Web Session Object as map-Key and a List<Future> as map-value. I want that once the session expires (and there's no strong reference to that Session in my App Context) the List<Future> is iterated and cancel is called on all the remaining Futures that are waiting to be executed. This to avoid having scheduled jobs that will run even if the User Session is expired.
mickthompson
[...continue] In this way the Futures cancellation can be managed automatically. It is just a way to experiment weak references... but I still don't get why if I continue polling the referenceQueue it doesn't return anything even if something gets removed from the WeakHashMap
mickthompson
+1  A: 

From a comment on another answer:

I want that once the session expires (and there's no strong reference to that Session in my App Context) the List is iterated and cancel is called on all the remaining Futures that are waiting to be executed. This to avoid having scheduled jobs that will run even if the User Session is expired.

This sounds like a job for a HttpSessionBindingListener

Alan Krueger
This is not an answer to the original question. But for the concrete use-case here that is indeed a much better approach. This way the futures can be cancelled as soon as the session expires, instead of at some random time later when garbage collection happens to kick in.
Wouter Coekaerts