2011-12-02 202 views
51

我在程序上运行了一个堆转储。当我在内存分析工具中打开它时,发现org.logicalcobwebs.proxool.ProxyStatementjava.lang.ref.Finalizer占用大量内存。这是为什么?是内存泄漏?为什么java.lang.ref.Finalizer吃了这么多内存

screenshot

+0

“图片”链接转到看起来是你的twitter个人资料。 –

+0

@ R.MartinhoFernandes我认为它可以看到他用Twitter发布的图片。 – Oliver

回答

49

一些类实现Object.finalize()方法。重写此方法的对象需要由后台线程调用终结器调用,并且在这种情况发生之前无法清理它们。如果这些任务很短,而且不会丢弃其中的许多,那么这一切都会很好。但是,如果要创建大量这些对象和/或它们的终结器需要很长时间,则需要完成对象的队列。这个队列有可能用完所有的内存。

的解决方案是

  • 如果你可以(如果你正在写的类的对象)不使用的finalize()d对象
  • 使敲定很短的(如果你要使用它)
  • 不要每次都放弃这样的对象(尝试重新使用它们)

的最后一个选项可能是最适合你,你正在使用现有的库。

+12

选项#4 - 避免使用(over-)使用终结器的库。 –

+3

选项#1的变体;) –

+0

也许问题是Finalizer线程的原因。 一个类重写finalize methond,导致Finalizer线程死锁 – fuyou001

7

从我能做出来的事情来看,Proxool是一个JDBC连接的连接池。这表明问题在于你的应用程序正在滥用连接池。而不是在语句对象上调用close,您的代码可能会丢弃它们和/或它们的父连接。 Proxool依靠终结器来关闭底层驱动程序实现的对象......但是这需要那些Finalizer实例。这也可能意味着,您正在导致连接更频繁地打开/关闭(实际)数据库连接,这会影响性能。

因此,我建议您检查泄漏的ResultSet,Statement和/或Connection对象的代码,并确保您在finally块中关闭它们。


看着内存转储,我期望你关心的是898,527,228字节在哪里。绝大多数由终止器对象保留,其ID为2aab07855e38。如果你仍然有转储文件,看看Finalizer指的是什么。它看起来比Proxool对象更有问题。

+0

谢谢,但我不能找到JDBC连接轮询memoy泄漏的原因 – fuyou001

+0

嗯,我不能,除非我看到你的源代码。 (而且我不准备花时间拖网通过它......) –