Java垃圾回收器 - “获取”已删除的对象

4

有没有可能查看将被垃圾收集器删除的对象?我不需要对象的内容,但需要对象的类。

我正在尝试编写一个实时应用程序,它创建和删除大量对象,一段时间后应用程序变慢。目前我不确定是我的代码还是外部库的问题。因此,最完美的输出应该是识别所有已删除的类,以及它们的“计数”(删除了多少个这些对象)。

希望有人能帮助我。

最好的祝福, Michael


我会使用内存分析器。这可以显示对象的分配位置以及它们被保留的原因(这可能是减速的原因)。我使用YourKit,因为它更易于使用和更强大。VisiualVM是免费的。 - Peter Lawrey
5个回答

6

顺便提一下:Visualvm也包含在JDK中:jdk..../bin/jvisualvm.exe(适用于Windows) - Michael

3
如何覆盖对象的finalize方法,并在其中记录类的名称?但要注意,这可能会防止垃圾回收器对对象进行垃圾回收。
您的类可能如下所示:
public class MyObject {

    @Override
    public void finalize() throws Throwable {
        logger.debug("Object of class {} being garbage collected", this.getClass().getName());
    }
}

这是 Object.finalize() 方法的签名和文档。
/**
 * Called by the garbage collector on an object when garbage collection
 * determines that there are no more references to the object.
 * A subclass overrides the <code>finalize</code> method to dispose of
 * system resources or to perform other cleanup. 
 * <p>
 * The general contract of <tt>finalize</tt> is that it is invoked 
 * if and when the Java<font size="-2"><sup>TM</sup></font> virtual 
 * machine has determined that there is no longer any
 * means by which this object can be accessed by any thread that has
 * not yet died, except as a result of an action taken by the
 * finalization of some other object or class which is ready to be
 * finalized. The <tt>finalize</tt> method may take any action, including
 * making this object available again to other threads; the usual purpose
 * of <tt>finalize</tt>, however, is to perform cleanup actions before 
 * the object is irrevocably discarded. For example, the finalize method 
 * for an object that represents an input/output connection might perform
 * explicit I/O transactions to break the connection before the object is
 * permanently discarded. 
 * <p>
 * The <tt>finalize</tt> method of class <tt>Object</tt> performs no 
 * special action; it simply returns normally. Subclasses of 
 * <tt>Object</tt> may override this definition.
 * <p>
 * The Java programming language does not guarantee which thread will 
 * invoke the <tt>finalize</tt> method for any given object. It is 
 * guaranteed, however, that the thread that invokes finalize will not 
 * be holding any user-visible synchronization locks when finalize is 
 * invoked. If an uncaught exception is thrown by the finalize method, 
 * the exception is ignored and finalization of that object terminates.
 * <p>
 * After the <tt>finalize</tt> method has been invoked for an object, no 
 * further action is taken until the Java virtual machine has again 
 * determined that there is no longer any means by which this object can 
 * be accessed by any thread that has not yet died, including possible
 * actions by other objects or classes which are ready to be finalized, 
 * at which point the object may be discarded.
 * <p>
 * The <tt>finalize</tt> method is never invoked more than once by a Java
 * virtual machine for any given object.
 * <p>
 * Any exception thrown by the <code>finalize</code> method causes 
 * the finalization of this object to be halted, but is otherwise 
 * ignored. 
 *
 * @throws Throwable the <code>Exception</code> raised by this method
 */
protected void finalize() throws Throwable { }

1
这个想法看起来很不错。对于我的问题,它不适用,因为我认为问题来自一个外部库,我无法覆盖finalize方法。但是感谢您的回答! - Michael
@Michael,在这种情况下,你必须像其他人建议的那样使用一些分析工具。 - adarshr

2

那些未被垃圾回收的对象难道不更有意思吗?

无论如何,像VisualVM这样的内存分析工具是你真正需要的。它可以精确地显示你的应用程序中每个类存在多少个对象,并且还可以通过比较垃圾收集前后的堆转储来识别已被垃圾回收的类和对象计数。


1
我建议您使用任何Java分析器,如JProfiler、Yourkit等。 非常容易看到垃圾收集的对象数量以及对象类型。

1
垃圾回收的线程运行在低优先级上。因此,这个线程没有机会执行清理任务。
垃圾回收线程也不保证总是运行。在您的应用程序中,垃圾回收的低优先级线程没有机会执行应用程序线程。因此,堆不能从未使用的对象中清除,因此由于受限堆大小,应用程序变慢。
您可以通过覆盖 `public void finalize()` 方法来计算垃圾回收的对象数量。有关更多详细信息,请参见 javadoc
我建议您使用一些Java分析器来诊断内存问题。

谢谢你的答复。是否有可能以更高的优先级运行垃圾回收呢?问题是,由于我已经拥有约5GB的堆空间,并且由于我创建和删除了很多对象,因此垃圾回收对该应用程序非常重要。 - Michael
你不能改变垃圾回收器的优先级。你所能做的就是在对象使用后立即将引用置为空,如果可能的话。此外,不要创建不必要的对象,需要时才进行惰性创建(单例设计模式)。还可以使用工厂设计模式来控制和缓存对象的创建。 - Amit Patel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接