简体   繁体   English

列出正在垃圾收集的实例

[英]List instances being garbage collected

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. 我尝试了-XX:+PrintGC-XX:+PrintGCDetails ,但这仅显示了释放的内存量。

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. 编辑:在这种情况下,问题是我的Java进程大小正在增加,并且我使用了很多线程,据我所知,用于所有线程的内存不在堆大小上,而是在线程堆栈中,我不知道如何检查它的状态。

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. 不,您不会通过日志记录从JVM中获取实例级(类不是GC-d)信息,没有此类设置。

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. 深入了解GC如何针对特定类的实例执行操作的唯一好选择是获取内存转储并进行比较。 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. 如果您真的认为问题是由线程数量过多引起的,则需要使用-Xss选项开始配置允许的堆栈大小。 Since this memory gets reserved even if not used by the thread, you might run out of memory just by spawning too many threads. 由于即使不使用该线程也会保留该内存,因此您可能仅通过产生太多线程来耗尽内存。

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: 如果要监视特定类的实例,则可以让它们覆盖finalize()方法,该方法在垃圾回收实例时调用:

@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!

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. 这意味着堆栈上的变量是GC根。

Yourkit profiler has a GC root view . Yourkit探查器具有GC根视图 Other profilers should at least show you the shortest path(s) of any live object to GC roots. 其他探查器至少应向您显示任何活动对象到GC根的最短路径。

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. 或者,您可以简单地附加调试器,挂起整个VM,并使用调试器的堆栈和堆漫游功能来检查局部变量当前持有的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM