68

我在我的程序上运行了一个堆转储。当我在内存分析器工具中打开它时,我发现java.lang.ref.Finalizerfororg.logicalcobwebs.proxool.ProxyStatement正在占用大量内存。为什么会这样?

截屏

4

2 回答 2

69

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

解决方案是

  • 如果可以,请不要使用 finalize()d 对象(如果您正在为对象编写类)
  • 使 finalize 非常短(如果你必须使用它)
  • 不要每次都丢弃此类对象(尝试重复使用它们)

当您使用现有库时,最后一个选项可能最适合您。

于 2011-12-02T10:47:41.807 回答
11

据我所知,Proxool 是一个用于 JDBC 连接的连接池。这向我表明问题在于您的应用程序正在滥用连接池。close您的代码可能会删除它们和/或它们的父连接,而不是调用语句对象。Proxool 依赖终结器来关闭底层驱动程序实现的对象……但这需要那些终结器实例。这也可能意味着您导致连接打开/关闭(实际)数据库连接的频率超出了必要的频率,这对性能不利。

所以我建议你检查你的代码是否有泄漏的 ResultSet、Statement 和/或 Connection 对象,并确保你将它们关闭在finally块中。


查看内存转储,我希望您关心 898,527,228 字节的去向。绝大多数由 id 为的 Finalizer 对象保留2aab07855e38。如果您仍然有转储文件,请查看 Finalizer所指的内容。它看起来比 Proxool 对象更成问题。

于 2011-12-02T11:05:48.203 回答