有没有办法查看哪些实例是垃圾回收?
我尝试了-XX:+PrintGC
和-XX:+PrintGCDetails
,但这只显示了正在释放的内存量。
编辑:在这种特殊情况下,问题是我的java进程大小正在增加,而且我使用了很多线程,而且据我所知,用于所有的内存线程不在堆大小上,而是在线程堆栈中,我不知道如何检查它的状态。
答案 0 :(得分:2)
不,您不会通过日志记录从JVM中获取实例级别(类不是GC-d)信息,没有这样的设置。
了解GC如何针对特定类的实例执行操作的唯一好方法是采用memory dumps并进行比较。这样您就可以发现大量实例从一个特定的类保留。 (例如,您不小心保留了对一组流对象的引用)
更新:
既然你提到你有很多线程,那就多了一些信息。线程堆栈只包含本地原语,而不包含对象引用。所以你很可能 在heapdump中找到你的溢出对象。如果您确实认为问题是由线程数量过多引起的,那么您需要使用-Xss
选项开始配置允许的堆栈大小。由于该内存即使没有被线程使用也会被保留,因此只需生成太多线程就可能会耗尽内存。
答案 1 :(得分:1)
如果要监视特定类的实例,可以让它们覆盖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!
答案 2 :(得分:0)
根据我的理解,用于所有线程的内存不在堆大小上,而是在线程堆栈中,我不知道如何检查它的状态。
线程堆栈通常不是很大。但是一个线程可能会保留堆上的对象。这意味着堆栈上的变量是GC根。
Yourkit Profiler有一个GC root view。其他分析器至少应该向您显示GC根源的任何活动对象的最短路径。
或者,您可以简单地附加调试器,挂起整个VM并使用调试器堆栈和堆行走功能来检查本地变量当前持有的内容。