Java GC – 有一种方法可以确定收集哪些对象

我正在尝试使用-verbosegc标志来监控应用中的gc活动。 我可以看到有完整和次要的集合,但有没有办法确定(确定事件/ vm标志/其他什么)实际收集的对象?

谢谢!

有关内存中对象的一般信息,我建议您查看jvisualvm(它位于JDK的bin文件夹中)。 它有很多关于VM在程序运行时正在做什么的有用信息,包括有关各种对象和内存状态的信息。

如果您想要更具体的东西,可以使用WeakReferences和ReferenceQueues。 如果您只对几种类型的对象感兴趣,则此选项可能是可行的。 您可以使用公共ReferenceQueue创建对象的WeakReference,然后让另一个线程定期检查Queue(请注意,队列只表示对象可以访问,而不是实际收集它们):

static ReferenceQueue MY_QUEUE = new ReferenceQueue(); static class MyReference extends WeakReference{ public final String name; public MyReference(MyObject o, ReferenceQueue q){ super(o, q); name = o.toString(); } } static{ Thread t = new Thread(){ public void run(){ while(true){ MyReference r = (MyReference)MY_QUEUE.remove(); System.out.println(r.name+" eligible for collection"); } } } t.setDaemon(true); t.start(); } public MyObject(){ //normal init... new MyReference(this, MY_QUEUE); } 

我自己没有使用过这个标志-XX:-TraceClassUnloading 。 它意味着跟踪类的卸载。

在GC收集对象之前调用Object类的finalize方法。 在您的类中重写方法,如下所示:

 @Override protected void finalize() throws Throwable { System.out.println(this+" collected"); super.finalize(); } 

请注意,您只能使用此方法监视自己的类。 因此,由于String是最终类,因此无法使用这种方式监视String对象。

我知道这不是你想要解决问题的方式,但无论如何它可能都是有用的。

您可以通过覆盖finalize方法在自己的对象上捕获事件。 它不能100%保证对象将是Garbage Collected,因为它可以创建对自身的引用,但它是一个开始。

看看这篇文章,这是一个非常好的GC教程。

我不完全确定你为什么需要知道这一点。 大多数人都想知道这一点,以确定他们是否有内存泄漏。 (在java中,这意味着通过保持对对象的引用来保持对象的活动)。

Netbeans有很好的工具来查看任何java应用程序的内存使用(也就是那些不是从netbeans运行的应用程序!)它们可以告诉你已经收集了多少对象以及你的内存使用情况,还有更多有用的统计数据。

要分析内存问题,您需要检查哪些对象不是 GCed,而不是检查哪些对象得到了GCed。

要检查哪些对象是GCed,您可以随时使用任何分析器,如Jprofiler等。

通常,您无法确定回收哪个对象。 但是,你可以找到它的一个子集,但你必须使用Weak,Soft和Phantom引用来引用它们。 通常,您要创建一个对象,然后使用其中一个引用来引用它。 看到这篇文章。