Reputation: 4844
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
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
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