如何找到哪个Finalizer非常耗时

时间:2016-11-12 12:06:41

标签: java garbage-collection jvm finalizer finalize

我正在开发一个应用程序,其目的是尽可能快地计算报告。

我的应用程序使用大量内存;超过100 Go。

自上次发布以来,我发现性能大幅放缓。我的调查显示,在计算过程中,我在40到60秒之间收集了很多垃圾! (JMC告诉我他们 SerialOld 但我不知道它究竟意味着什么)当然,当JVM是垃圾收集时,应用程序绝对是冻结的

我现在正在调查这些垃圾收集的来源......这是一项非常艰苦的工作。

我怀疑,如果这些垃圾收集很长,那是因为他们在finalize函数中花费了很多次(我知道,在我们从其他团队整合的所有库中,有些他们使用终结者)

但是,我不知道如何确定(或不)这个假设;如何找到哪个终结器很耗时。

我正在寻找一个好的工具甚至是一个好的方法

  

以下是通过JVisualVM收集的数据   Taken from JVisualVM's "Tracer" tab

     

正如你所看到的,当我有一个时,我总是有很多“待定终结者”   记录旧垃圾

     

令人惊讶的是,当我使用JVisualVM时,上图   从右到左定期滚动。当旧垃圾是   触发,滚动停止(直到这里,它看起来正常,这是   最终的世界)。但是,当滚动突然重启时,确实如此   不是从旧垃圾的末尾,而是从Pending Serializer的末尾

     

这让我觉得终结器阻止了JVM

     

有没有人对此有解释?

非常感谢你 菲利普

2 个答案:

答案 0 :(得分:2)

  

我的应用程序使用大量内存;超过100 Go。

     

JMC告诉我他们是SerialOld,但我不知道它究竟意味着什么

如果您使用100GB堆的串行收集器,那么可以预期长时间暂停,因为串行收集器是单线程的,并且一个核心只能在每个单位时间内节省大量内存。

只需选择任何一个多线程收集器就可以产生更短的暂停时间。

  

但是,我不知道如何确定(或不)这个假设;如何找到哪个终结器很耗时。

通常:收集更多数据。对于GC相关的事情,您需要启用GC日志记录,在Java代码中花费的时间(无论是您的应用程序还是第三方库),您需要一个分析器。

答案 1 :(得分:1)

以下是我要调查终结者理论的方法。

  1. 使用您喜欢的Java分析器启动JVM。

  2. 让它运行足够长的时间以获得完整的堆。

  3. 启动探查器。

  4. 触发垃圾回收。

  5. 停止分析器。

  6. 现在,您可以使用分析器信息来确定哪些(如果有)finalize方法占用了大量时间。

    但是,我怀疑真正的问题是内存泄漏,而且你的JVM正在到达堆满了无法恢复的对象的程度。这可以解释频繁的" SerialOld"垃圾收集。

    或者,这可能只是一个大堆问题。 100Gb是......大。