列出被垃圾收集的实例

List instances being garbage collected

有没有办法查看哪些实例正在被垃圾回收?

我尝试了 -XX:+PrintGC-XX:+PrintGCDetails,但它们只显示了释放的内存量。

编辑: 在这种特殊情况下,问题是我的 java 进程大小在增加,我使用了很多线程,为什么我知道,用于所有线程的内存不在堆大小上,而是在线程堆栈中,我不知道如何检查它的状态。

不,您不会通过日志记录从 JVM 中获取实例级(classes 不是 GC-d)信息,没有这样的设置。

了解 GC 如何针对特定 class 实例执行的唯一好的选择是获取 memory dumps 并比较它们。通过这种方式,您可以从保留的特定 class 中发现大量实例。 (例如,您不小心保留了对一组流对象的引用)

更新:

既然你提到你有很多话题,那么就多说一点。线程堆栈仅包含本地原语,不包含对象引用。因此,您很可能 在堆转储中找到溢出的对象。如果您真的认为您的问题是由线程数量过多引起的,那么您需要开始使用 -Xss 选项配置允许的堆栈大小。由于此内存即使未被线程使用也会被保留,因此您可能会 运行 仅仅因为产生太多线程而导致内存不足。

如果你想监控 specific 类 的实例,你可以让它们覆盖 finalize() 方法,该方法在实例被调用时调用收集的垃圾:

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

这里有一些测试代码展示了它的实际效果:

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!");
    }
}

输出:

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.

线程堆栈通常不是很大。但是一个线程可能会持有堆上的对象。这意味着堆栈上的变量是 GC 根。

Yourkit 分析器有一个 GC root view。其他分析器至少应该向您显示任何活动对象到 GC 根的最短路径。

或者,您可以简单地附加一个调试器,挂起整个 VM 并使用调试器堆栈和堆遍历功能来检查局部变量当前持有的内容。