简体   繁体   English

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

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

I have a memory dump which I has made from a dying application. 我有一个内存转储,我从一个垂死的应用程序。 It has consumed all available heap (-Xmx1024m). 它消耗了所有可用堆(-Xmx1024m)。 It uses com.gargoylesoftware.htmlunit.WebClient to crawl web pages. 它使用com.gargoylesoftware.htmlunit.WebClient来抓取网页。 Makes a few http requests per minute, dies in several days. 每分钟发出一些http请求,几天后就会死掉。 As I see from the dump, it has ~1750 instances of HtmlPage class, each is with tones of related objects, including full content of a crawled page. 正如我从转储中看到的那样,它有大约1750个HtmlPage类实例,每个实例都包含相关对象的音调,包括已爬网页面的完整内容。

I cannot understand why the HtmlPage are not garbage collected. 我无法理解为什么HtmlPage不是垃圾收集的。 I have investigated instance references and I don't see any my code holding a reference to it, and VisualVM says that "No GC root found". 我已经调查了实例引用,我没有看到任何我的代码持有对它的引用,并且VisualVM说“找不到GC根”。 As I understand it should mean the object is eligible for gc, but it doesn't work. 据我所知,它应该意味着该对象符合gc的条件,但它不起作用。

The application is running as a simple standalone process, it doesn't use any web containers or application servers. 应用程序作为一个简单的独立进程运行,它不使用任何Web容器或应用程序服务器。

Any hints? 任何提示? What else should I look into? 我还应该研究什么?

Specs: 眼镜:

  • htmlunit v2.7 htmlunit v2.7
  • java version "1.6.0_13" Java(TM) SE Runtime Environment (build 1.6.0_13-b03) Java HotSpot(TM) Server VM (build 11.3-b02, mixed mode) 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 11:42:39 EST 2008 i686 i686 i386 GNU/Linux Linux my.lan 2.6.18-128.el5#1 SMP Wed Dec 17 17:42:39 EST 2008 i686 i686 i386 GNU / Linux

Update1 UPDATE1

I have tried to analyse the dump by the YourKit Java Profiler. 我试图通过YourKit Java Profiler分析转储。 It shows me a lot of java.lang.ref.Finalizer objects with 310mb retained size. 它向我展示了许多具有310mb保留大小的java.lang.ref.Finalizer对象。 They are created for the net.sourceforge.htmlunit.corejs.javascript.NativeGenerator#finalize() finalizer, and the NativeGenerator refers to Window , then to HtmlPage and to everything. 它们是为net.sourceforge.htmlunit.corejs.javascript.NativeGenerator#finalize()终结器创建的,而NativeGenerator是指Window ,然后是HtmlPage和所有内容。

Does anybody know why are they stay in memory? 有谁知道他们为什么留在记忆中?

Note : Curious, but VisualVM showed "pending finalization" as zero. 注意 :好奇,但VisualVM显示“待定完”为零。

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

When an object has non trivial finalize() method, when creating an instance of the object the JVM creates java.lang.ref.Finalizer that holds reference to the created object so it doesnt get garbage collected before the finalize() method is finished. 当一个对象具有非常重要的finalize()方法时,在创建对象的实例时,JVM会创建java.lang.ref.Finalizer,该java.lang.ref.Finalizer保存对创建的对象的引用,因此在finalize()方法完成之前它不会被垃圾收集。 The memory leak comes from those java.lang.ref.Finalizer-s not being cleared on time. 内存泄漏来自那些没有按时清除的java.lang.ref.Finalizer-s。 The clearing of these finalizers is done by a separate finalizer daemon thread that has lower priority, so if you create a lot of instances of objects with implemented finalize() method, in time you run out of memory. 清除这些终结器是由一个具有较低优先级的单独的终结器守护程序线程完成的,因此如果使用已实现的finalize()方法创建大量对象实例,则会导致内存不足。

Its all described very good in: 它描述的非常好:

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

This is what they suggest as a solution: 这是他们建议的解决方案:

"One obvious way is to increase the priority of the "Finalizer" daemon thread - there is no API for this, so you have to run through all the threads to find it by name, then increase it's priority." “一个显而易见的方法是增加”Finalizer“守护程序线程的优先级 - 没有这个API,所以你必须遍历所有线程才能按名称找到它,然后增加它的优先级。”

Good luck 祝好运

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

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