列出被垃圾收集的实例
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 并使用调试器堆栈和堆遍历功能来检查局部变量当前持有的内容。
有没有办法查看哪些实例正在被垃圾回收?
我尝试了 -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 并使用调试器堆栈和堆遍历功能来检查局部变量当前持有的内容。