当前位置: 首页 > 知识库问答 >
问题:

eclipse内存分析器看到整个堆转储(8GB)中的一小部分(363,2MB)

丁灿
2023-03-14

我试图调查java.lang.OutOfMemoryError:GC限制超出这是在部署在Tomcat中的web应用程序负载较高时发生的。堆大小设置为8GB(-XMS2048M-XMX8192M)

在某个时间点,由于GC activity开销,我们应用程序变得没有响应。我可以在日志中看到完整的GC连续发生多次。因此,我使用以下命令(jmap-f-dump:format=b,file=/root/dump2.hprof4963)进行堆转储。包含转储的文件大小为9GB。转储后(应用程序被冻结约45分钟),发生多个完整GC直到抛出OutOfMemoryError

下面是GC activity的日志示例

[Full GC [PSYoungGen: 932096K->875513K(1864128K)] [ParOldGen: 5592447K->5592447K(5592448K)] 6524543K->6467961K(7456576K) [PSPermGen: 112285K->112285K(262144K)], 12.3954040 secs] [Times: user=47.60 sys=0.43, real=12.39 secs]
[Full GC [PSYoungGen: 932096K->890562K(1864128K)] [ParOldGen: 5592447K->5592447K(5592448K)] 6524543K->6483009K(7456576K) [PSPermGen: 112285K->112285K(262144K)], 12.6131900 secs] [Times: user=48.45 sys=0.49, real=12.61 secs]
[Full GC [PSYoungGen: 932096K->895268K(1864128K)] [ParOldGen: 5592447K->5592447K(5592448K)] 6524543K->6487715K(7456576K) [PSPermGen: 112285K->112285K(262144K)], 12.9488670 secs] [Times: user=49.61 sys=0.46, real=12.95 secs]

Heap
 PSYoungGen      total 1864128K, used 896698K [0x0000000755560000, 0x0000000800000000, 0x0000000800000000)
  eden space 932096K, 96% used [0x0000000755560000,0x000000078c10e8a8,0x000000078e3a0000)
  from space 932032K, 0% used [0x000000078e3a0000,0x000000078e3a0000,0x00000007c71d0000)
  to   space 932032K, 0% used [0x00000007c71d0000,0x00000007c71d0000,0x0000000800000000)
ParOldGen       total 5592448K, used 5592447K [0x0000000600000000, 0x0000000755560000, 0x0000000755560000)
  object space 5592448K, 99% used [0x0000000600000000,0x000000075555ff30,0x0000000755560000)
PSPermGen       total 262144K, used 112285K [0x00000005e0000000, 0x00000005f0000000, 0x0000000600000000)
  object space 262144K, 42% used [0x00000005e0000000,0x00000005e6da7530,0x00000005f0000000)

heap dump is taken (ca 45minutes freeze)
[Full GC [PSYoungGen: 932096K->903362K(1864128K)] [ParOldGen: 5592447K->5592447K(5592448K)] 6524543K->6495810K(7456576K) [PSPermGen: 112285K->112285K(262144K)], 2883.9864390 secs] [Times: user=49.41 sys=0.47, real=2884.17 secs]
[Full GC [PSYoungGen: 932096K->897728K(1864128K)] [ParOldGen: 5592447K->5592444K(5592448K)] 6524543K->6490173K(7456576K) [PSPermGen: 112288K->112288K(262144K)], 13.3092680 secs] [Times: user=50.75 sys=0.40, real=13.31 secs]

为了分析堆转储,我在eclipse memory analyzer(MAT)中打开了它。不幸的是,MAT显示堆大小为363.2MB(在overview选项卡或heap dump details选项卡中),而根据GC日志,heap被填充到6467961K(6.4G)。不可达对象直方图显示总数为75 511 736(75 MB)。直方图视图还确认了总浅堆为380 837 136(363.2MB)

我的问题是,如果GC不能回收内存,为什么MAT不显示来自堆转储的所有对象?

env details:
Eclipse Memory Analyzer Version 1.2.1
heap dump taken on
java version "1.7.0_13"
Java(TM) SE Runtime Environment (build 1.7.0_13-b20)
Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)

下面是MAT中导入堆转储的截图:

  • 概述
  • 无法访问

共有2个答案

潘琨
2023-03-14

这是MAT在收集如此大堆的堆转储时的通常行为。我经常收集8GB堆的堆转储,通常会得到一个显示大约1GB活动对象的MAT配置文件。

45分钟的冻结也在意料之中。我的解释是,在堆转储收集时间内,会发生几个FullGC循环,这减小了所获取的实际堆转储的大小。但我没有找到官方的解释或参考文件,说明为什么会有如此大的差别。

此外,请参阅此引用-MAT并不显示完整的堆:

症状:交互监视内存使用情况时,使用的堆大小比MAT报告的要大得多。

在创建索引的过程中,内存分析器会移除无法到达的对象,因为各种垃圾收集器算法往往会留下一些垃圾(如果对象太小,移动和重新分配地址会非常昂贵)。不过,这一比例不应超过3%至4%。如果您想知道删除了哪些对象,请按照下面的说明启用调试输出:memoryanalyzer/faq#enable_debug_output

洪增
2023-03-14

默认情况下,MAT不显示不可达对象。

您可以通过转到Preferences->Memory Analyzer->Keep Unreachable objects来启用该选项。启用该选项后,再次加载堆。

启用该选项后,它将显示完整的堆。即使我也在同样的情况下,无法在网上获得很多信息,我的经理给了我一个选择。希望能有所帮助。

 类似资料:
  • 我已经用工具从运行了几天的Java应用程序中生成了一个堆转储文件,这将导致一个很大的二进制堆转储文件。 我如何在IntellIJ IDEA中对这个堆转储执行内存分析? 我知道有一些用于Eclipse和Netbeans的工具,但如果可能的话,我更愿意使用IDEA。 分析的基本结果将告诉我每个对象在内存中的实例数(每个类),以便我能够开始调试内存泄漏。

  • 我有一个非常奇怪的问题。我有一个30 GB的堆转储,我想在我的笔记本电脑上分析相同的(它有8 GB的内存)。我试着用MAT和IBM堆分析器这样做,但是根据他们的建议,Xmx大小应该超过转储大小。我也试着用MAT的文件分析堆转储,但是收到内存错误。 关于如何成功分析笔记本电脑上的垃圾,有什么建议吗? 提前谢谢!

  • 我试图分析我的Java applet的堆转储,它耗尽了堆空间,即使我增加堆大小,如本文所示。applet:Java堆空间 今天上午我做了一些堆转储(是的...它可能做数字转储),我试图用MAT和Visual VM1.3.5来分析它们。运行泄漏测试后,主要的怀疑对象是org.eclipse.jdt.internal.core.javaModelManager和org.eclipse.jst.jee.

  • 我正在经历内存泄漏,这里有一些细节。 在泄漏后, null null 我很惊讶顶部、堆转储大小和实际堆大小之间的差异。我猜测top和heap之间的区别是垃圾收集器堆和本地堆区域的可能性。但是,为什么堆转储文件大小和实际堆大小(来自eclipse MAT analyzer)会不同呢? 对这个问题有什么见解吗? 更新/回答 一些建议是使用jcmd(https://docs.oracle.com/jav

  • 我已经下载了EclipseMat,并尝试在Windows上启动它。 执行显示一个弹出窗口,显示与此消息不兼容的JVM:JVM的1.8.0242版本不适用于此产品。版本:11或更高版本是必需的。 如本文所述,我创建了一个目录,并复制了一个解决问题的OpenJDK 16。 但是我不觉得这个解决方案很优雅。所以我试图在中添加参数,并试图创建一个文件作为文档的引用。它不起作用! 有没有一种方法可以配置JV