繁体   English   中英

狩猎内存泄漏,VisualVM:“没有发现GC根”。 下一步是什么?

[英]Hunting memory leaks, VisualVM: “No GC root found”. What's next?

我有一个内存转储,我从一个垂死的应用程序。 它消耗了所有可用堆(-Xmx1024m)。 它使用com.gargoylesoftware.htmlunit.WebClient来抓取网页。 每分钟发出一些http请求,几天后就会死掉。 正如我从转储中看到的那样,它有大约1750个HtmlPage类实例,每个实例都包含相关对象的音调,包括已爬网页面的完整内容。

我无法理解为什么HtmlPage不是垃圾收集的。 我已经调查了实例引用,我没有看到任何我的代码持有对它的引用,并且VisualVM说“找不到GC根”。 据我所知,它应该意味着该对象符合gc的条件,但它不起作用。

应用程序作为一个简单的独立进程运行,它不使用任何Web容器或应用程序服务器。

任何提示? 我还应该研究什么?

眼镜:

  • htmlunit v2.7
  • java版“1.6.0_13”Java(TM)SE运行时环境(版本1.6.0_13-b03)Java HotSpot(TM)服务器VM(版本11.3-b02,混合模式)
  • Linux my.lan 2.6.18-128.el5#1 SMP Wed Dec 17 17:42:39 EST 2008 i686 i686 i386 GNU / Linux

UPDATE1

我试图通过YourKit Java Profiler分析转储。 它向我展示了许多具有310mb保留大小的java.lang.ref.Finalizer对象。 它们是为net.sourceforge.htmlunit.corejs.javascript.NativeGenerator#finalize()终结器创建的,而NativeGenerator是指Window ,然后是HtmlPage和所有内容。

有谁知道他们为什么留在记忆中?

注意 :好奇,但VisualVM显示“待定完”为零。

确保在完成页面后调用webClient.closeAllWindows() - 否则JavaScript线程将继续运行,保持对页面资源的引用等。

当一个对象具有非常重要的finalize()方法时,在创建对象的实例时,JVM会创建java.lang.ref.Finalizer,该java.lang.ref.Finalizer保存对创建的对象的引用,因此在finalize()方法完成之前它不会被垃圾收集。 内存泄漏来自那些没有按时清除的java.lang.ref.Finalizer-s。 清除这些终结器是由一个具有较低优先级的单独的终结器守护程序线程完成的,因此如果使用已实现的finalize()方法创建大量对象实例,则会导致内存不足。

它描述的非常好:

http://www.fasterj.com/articles/finalizer2.shtml

这是他们建议的解决方案:

“一个显而易见的方法是增加”Finalizer“守护程序线程的优先级 - 没有这个API,所以你必须遍历所有线程才能按名称找到它,然后增加它的优先级。”

祝好运

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM