2

Is there a way to see which instances are being garbage collected?

I tried -XX:+PrintGC and -XX:+PrintGCDetails, but that only shows the amount of memory being released.

EDIT: In this particular case, the problem is that my java process size is increasing, and I'm using a lot of threads, and for what I understand, the memory used for all the threads isn't on the heap size, but in the thread stack, which I don't know how to inspect it's state.

4
  • 2
    Which classes or which instances? Commented Nov 4, 2015 at 13:06
  • Corrected it to instances. Commented Nov 4, 2015 at 14:49
  • what you want is a memory profiler. Commented Nov 4, 2015 at 16:39
  • @the8472 I'm currently using JProfiler, but I'm still looking for a way to "browse" trough the thread stack memory. I also added more details to the original question. Commented Nov 4, 2015 at 16:57

3 Answers 3

2

No, you will not get instance-level (classes are not GC-d) information out of a JVM via logging, there is no such setting for that.

The only good option to gain some insight into how GC is performing against instances of a specific class is to take memory dumps and compare them. This way you can spot huge number of instances from a specific class retained. (for example you are accidentally keeping references to a set of streamed objects)

UPDATE:

Since you mentioned that you have many threads, a bit more info on that. Thread-stack only contains local primitives, not object references. So it is very likely that you would find your overflowing objects in the heapdump. If you really believe that your problem is caused by the sheer number of your threads, that you need start configuring the the allowed stack size by using the -Xss option. Since this memory gets reserved even if not used by the thread, you might run out of memory just by spawning too many threads.

Sign up to request clarification or add additional context in comments.

2 Comments

The problem is that my java process size is increasing, and I'm using a lot of threads, and for what I understand, the memory used for all the threads isn't on the heap size, but in the thread stack, which I don't know how to inspect it's state.
@balizeiro The obvious solution is: don't use a lot of threads. They only slow the application down.
1

If you want to monitor instances of specific classes, you can have them override the finalize() method, which is called when the instance is being garbage collected:

@Override protected void finalize() throws Throwable { super.finalize(); // log whatever here } 

Here's some test code showing it in action:

public class MyClass { public static void main(String[] args) throws Exception { new MyClass(); System.gc(); Thread.sleep(1000); } @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("Goodbye, cruel world!"); } } 

Output:

Goodbye, cruel world! 

2 Comments

finalize does not guarantee that the object is or will ever be garbage collected, instead phantom references should be used instead - read this article for further information. Note however, that the target object will only be garbage collected when the phantom reference is also garbage collected or the reference queue containing the reference is cleared
@RomanVottner no one has suggested that finalize guarantees anything. However, finalize is guaranteed to be called when/if the object is being GC'd
0

and for what I understand, the memory used for all the threads isn't on the heap size, but in the thread stack, which I don't know how to inspect it's state.

Thread stacks typically aren't very large. But a thread may hold onto objects on the heap. That means variables on the stack are GC roots.

Yourkit profiler has a GC root view. Other profilers should at least show you the shortest path(s) of any live object to GC roots.

Alternatively you can simply attach a debugger, suspend the whole VM and use the debuggers stack and heap walking capabilities to inspect what's currently held by local variables.

3 Comments

"Thread stacks typically aren't very large." That's what I tough also. But what is happening right now is this: Heapsize: 2Gb, Permgen:400Mb, Size in taskmanager: 8.5Gb. That's why I was thought the other 6GB must be in the stack from all the threads
"size in the task manager" seems to be your original problem then, looks like your're suffering from the XY problem because you simply assume it's the threads. You you probably should look at more general SO questions how to pin down what actually consumes memory or ask a new question if you can't find anything.
I'm not assuming a XY problem because I already profiled my application and didn't find anything being kept in the heap after the GC runs. That's why I was trying to find a way to see what is happening with the threads since they are kept on a different part of the JVM.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.