views:

172

answers:

7

Hi all,

I'm trying to monitor the gc activity in my app, using -verbosegc flag. I can see there are full and minor collections, but is there a way to determine (subscrbing to events/vm flags/whatever) which objects actually collected?

Thanks!

A: 

I know this isn't how you'd like to solve your problem, but it might be useful anyway.

You can capture the event on your own objects by overriding the finalize method. It doesn't 100% guarantee that the object will be Garbage Collected since it can create references to itself, but it's a start.

Take a look at this article it's a pretty good GC Tutorial.

Allain Lalonde
A: 

finalize method of the Object class is called just before the GC collects the object. Override the method in your class as follows:

public void finalize() {
    System.out.println(this+" collected");
    super.finalize();
}

Note that you can only monitor your own classes with this method. So, since String is a final class, you cannot monitor a String object with this way.

sahs
Also beware that finalizers are rather expensive.
Stephen C
Hmm, no idea. Why is it expensive?
sahs
You can never be assured that the finalize method will be called, so this approach does not guarantee you see all garbage collects.
dafmetal
Actually you should not use finalizers at least on Sun's VM anyway. 1. The reason is that finalizers are not guaranteed to run 2. Finalizers actually impedes GC. When the collect encounters a out of scope object with a finalizer, it actually sets it aside. It'll then reclaim it at a later time. So every object with finalizer requires at least 2 GC cycle to clear. 3. Finalizers are not executed in any particular order. So if you have 2 objects with finalizers that require some sort of finalizer ordering, then this is not guranteed
Chuk Lee
@sahs - yes. Objects with finalizers need to be copied to "to space" and queued for finalization after the GC has completed. The objects then need to be de-queues, and the finalizers called for each one. Finally, the objects will then need to be GC'ed again. I don't know the exact numbers, but that could amount to 100s of extra instructions per object ... excluding the work done by the finalizers themselves.
Stephen C
First of all, you should be aware that finalize method is called not just after the object is released, in other words, it is not like c++ destructor. GC decides when to collect it, after it is released. However, sometimes a java program may exit before garbage collecting the objects. That is the case the finalize method is not called.
sahs
@Chuk Lee - read the original question. If the OP *really* needs to track when specific objects are GC'ed, finalizers are probably the only way to do it. (I agree with your general principal though ... and agree with others who say that the OP won't learn anything useful from this exercise.)
Stephen C
@Stephen - that makes sense :).
sahs
@Stephen - I am not saying that that using finalizer is the way or not to track GCed objects. I'm just saying in general that he should not use finalizers.
Chuk Lee
@Chuk ... did you read my sentences in parentheses?
Stephen C
A: 

I'm not entirely sure why you need to know this. Most people want to know this to determine if they have memory leaks. (In java that means that you keep an object alive by keeping a reference to an object).

Netbeans has great tools to look at the memory use of any java application (also the ones not running from netbeans!) They can tell you how many objects have been collected and where your memory usage is going, and many more useful statistics.

Thirler
A: 

To analyze memory problems you need to check which objects are not GCed, instead of checking which objects got GCed.

To check which objects are GCed you can always use any profiler like Jprofiler etc.

Suraj Chandran
+1  A: 

I havent used this flag myself -XX:-TraceClassUnloading meant to Trace unloading of classes.

JoseK
A: 

In general you cannot determine which object is reclaimed. You can however find get a subset of it, but you have to reference them using Weak, Soft and Phantom reference. In general what you do is create an object then reference it using one of those reference. See this article.

Chuk Lee
Is there a way to determine the collected objects using instrumentation?
Seffi
Not that I know of. Basically JMX gives you the same info from your GC output. You can find out how much memory is freed. You can find out what objects are live. So I guess in theory you can sort of do a guestimate between how much is freed and from what has disappeared. I've not really tried this.
Chuk Lee
+3  A: 

For general information about objects in memory I would suggest you look into jvisualvm (it is in the bin folder of your JDK). It has alot of useful information about what the VM is doing as your program runs, including information about the various objects, and memory state.

If you want something more specific you can use WeakReferences and ReferenceQueues. This option might be viable if you are only interested in objects of a few type. You can create a WeakReference to the objects as they are created with a common ReferenceQueue, and then have another thread check the Queue periodically (note that the queue only says the objects are reachable, not that they are actually collected):

static ReferenceQueue<MyObject> MY_QUEUE = new ReferenceQueue<MyObject>();
static class MyReference extends WeakReference<MyObject>{
  public final String name;
  public MyReference(MyObject o, ReferenceQueue<MyObject> q){
    super(o, q);
    name = o.toString();
  }
}

static{
  Thread t = new Thread(){
    public void run(){
      while(true){
        MyReference r = (MyReference)MY_QUEUE.remove();
        System.out.println(r.name+" eligible for collection");
      }
    }
  }
  t.setDaemon(true);
  t.start();
}

public MyObject(){
  //normal init...
  new MyReference(this, MY_QUEUE);
}
M. Jessup