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.

Lii
  • 11,553
  • 8
  • 64
  • 88
mickthompson
  • 389
  • 1
  • 4
  • 12

4 Answers4

1

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
  • 24,113
  • 5
  • 60
  • 79
  • 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 Jun 30 '10 at 07:33
  • @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 Jun 30 '10 at 12:30
  • 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, MyObj2> but it didn't work – mickthompson Jun 30 '10 at 16:07
  • 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 Jun 30 '10 at 18:19
  • 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 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 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 Jun 30 '10 at 21:32
  • [...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 Jun 30 '10 at 21:36
1

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
  • 4,701
  • 4
  • 35
  • 48
  • 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 Jul 14 '10 at 21:56
0

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
  • 131,802
  • 30
  • 241
  • 343
0

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