【问题标题】:is memory leak? why java.lang.ref.Finalizer eat so much memory是内存泄漏吗?为什么 java.lang.ref.Finalizer 吃掉这么多内存
【发布时间】:2012-01-11 09:47:14
【问题描述】:

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

【问题讨论】:

  • “图片”链接指向您的 Twitter 个人资料。
  • @R.MartinhoFernandes 我认为这是他在推特上托管的一张图片。

标签: java memory finalizer proxool


【解决方案1】:

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

解决办法是

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

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

【讨论】:

  • 选项 #4 - 避免使用(过度)使用终结器的库。
  • 选项 #1 的变体 ;)
  • 也许问题是终结器线程的原因。一个类重写finalize方法,导致Finalizer线程死锁
  • 如果你有一个在 finalise 中死锁的对象,除了修复错误或使用另一个库之外,你无能为力。它不是你可以从外部修复的。
  • 我注意到在 Android 上使用大量正则表达式模式/匹配器实例(在使用后立即释放)时发生这种情况,当我用完内存时,我看到 50% 的堆被由这些指向我的 Pattern 或 Matcher 实例的 FinalizerReferences 占用(并且在堆映射中不存在对这些对象的其他引用)。
【解决方案2】:

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

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


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

【讨论】:

    猜你喜欢
    • 2011-05-04
    • 2015-08-04
    • 2016-08-03
    • 2013-03-23
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多