selig
selig

Reputation: 4844

Timing the life of an object

Here is my problem - I want to time how long an object is alive (i.e. on heap) for from a given point (which may be object creation). I don't need to record how long this was at the point of death, just at some point.

My current idea is to create an extension of WeakReference that records the start and end time i.e.

public class WeakTimeReference extends WeakReference<Object> {

    private final long start;
    private long end = -1;;
    public WeakTimeReference(Object obj, ReferenceQueue<Object> queue){
        super(obj,queue);
        long = System.currentTimeMillis();      
    }

    public Long getLife(){ return (end == -1) ? null : end-start; }

}

And then add these to a WeakHashMap (so I can tell when I've already created a reference) i.e.

private Map<Object,WeakTimeReference> map = 
                   new WeakHashMap<Object,WeakTimeReference>();
private ReferenceQueue queue = new ReferenceQueue();
public void add(Object o){
    if(!map.containsKey(o))
        map.put(o,new WeakTimeReference(o,queue));
}

Then when I want to know the times I just look at queue i.e.

while(queue.poll()){
   WeakTimeReference ref = (WeakTimeReference) queue.remove();
   // do something with ref.getLife()
}

However, the issue is that I'm not sure how I would go about getting end set in a WeakTimeReference. There is no method to override in Reference that gets called when it is enqueued, or any such method in ReferenceQueue.

My only thought is that I could wrap up objects with a class that has a finalize method that does this for me and put these in a WeakHashMap pointed to by their wrapped object. But this seems very messy.

So my question is:

Is anyway to perform an action when a reference object gets placed on a reference queue?

Failing that, can anybody see a neater way for me to achieve this?

Upvotes: 2

Views: 84

Answers (2)

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 136062

Use a wrapper with callback handler which will notifiy an Observer when the object is GCed.

class Wrapper implements ObjectInterface {
   Object obj;
   Statistics statisics;
   long t0 = System.currentTimeMillis;
   ...
   protected finalize() {
      statisics.notify(obj, System.currentTimeMillis - t0);
   }
}

I think Spring AOP would work well for this task

Upvotes: 1

Bathsheba
Bathsheba

Reputation: 234785

Use a finalizer, but you must adhere to this pattern:

protected void finalize() throws Throwable
{
  try
  {
    // your code here
  }
  finally
  {
    super.finalize();
  }
}

or you'll get as close to undefined behaviour as you can with Java.

Upvotes: 2

Related Questions