“压缩 Perm Gen” 值代表什么?

4
我正在调查我们生产系统中的JVM崩溃,下面hs_err_pid日志文件片段中的以下内存值代表什么意思?
Heap
 par new generation   total 1258624K, used 955445K [0x00000005c0000000, 0x00000006155b0000, 0x000000066aaa0000)
  eden space 1118784K,  73% used [0x00000005c0000000, 0x00000005f1e52598, 0x0000000604490000)
  from space 139840K,  98% used [0x000000060cd20000, 0x00000006153db100, 0x00000006155b0000)
  to   space 139840K,   0% used [0x0000000604490000, 0x0000000604490000, 0x000000060cd20000)
 tenured generation   total 2796224K, used 1745107K [0x000000066aaa0000, 0x0000000715550000, 0x00000007c0000000)
   the space 2796224K,  62% used [0x000000066aaa0000, 0x00000006d52d4d90, 0x00000006c2e0c400, 0x0000000715550000)
 compacting perm gen  total 482944K, used 482943K [0x00000007c0000000, 0x00000007dd7a0000, 0x0000000800000000)
   the space 482944K,  99% used [0x00000007c0000000, 0x00000007dd79fff0, 0x00000007dd7a0000, 0x00000007dd7a0000)
No shared spaces configured.

我的关注点在于“压缩的Perm Gen”使用:这是指最大分配的Perm Gen堆的使用百分比,还是指最大堆的使用百分比,或者其他什么?提供的百分比似乎是已用/总数的除法,这是总分配的Perm Gen吗?由于我们的-XX:MaxPermSize设置为1GB...
除了Oracle whitepaper(未提及hs_err文件)之外,是否有其他有用的资源可以解释JVM崩溃时转储的数据?

如果你进行除法运算,你会得到它。Permgen使用的百分比为(11253K / 16384K)。 - zeller
抱歉,我的示例并不能很好地代表我们实际看到的错误。我已经更新了我的问题。 - seanhodges
啊,那我就不知道了。抱歉。 - zeller
2个回答

5
我从未找到过准确描述“压缩Perm Gen”值的参考文献,但我们自己的调查证明了报告的值是:
当前使用PermGen / 当前分配的PermGen
在我的问题示例中,这意味着已为PermGen分配了482944K的内存,并且在GC点之前已使用482943K(99%)。我们的最大PermGen大小设置为1048576K(1GB),因此收集过程有足够的保留资源可重新分配。
对于那些遇到类似问题的人 - 我们最终解决了我们的问题。在我们的情况下,问题最终是一个第三方库,该库使用了sun.misc.Unsafe类,当不正确使用时,它是臭名昭著的“不安全”的。
在这种情况下,一个用于克隆对象的逻辑片段向某些sun.misc.Unsafe操作传递了特定的ClassLoader以复制对象。在某些机器上,复制的对象经常处于损坏状态。当JVM尝试进行垃圾收集时,它最终会清理掉其中一个坏对象并崩溃。这总是导致我问题中描述的错误。

1
我猜最后与压缩PermGen无关。我认为所谓的“压缩”实际上是垃圾回收/卸载PermGen中的类。我进行了一个快速测试,确实是当前分配的PermGen而不是最大Perm空间。其他人曾经报告过CGLib在过去会填满PermGen,但自从Hibernate 3.3以来,它已经转换为Javassist,似乎缓解了这个问题。 - Christopher Yang
谢谢您确认这个问题,因此我已将我的问题标记为已解决。 - seanhodges

0

但是仅仅因为你将MaxPermSize设置为1GB并不意味着HotSpot会遵守它。我认为我从来没有得到过超过512MB的空间。你的JVM的482MB非常接近这个数字。

无论如何,512MB对于PermGen来说已经足够了,因为它只用于保存类的元数据,除非通过ClassLoader加载更多的类,否则它不会增长。所以问题是:你真的需要超过512MB来保存所有必要类的字节码大小吗?

很有可能你的系统实际上存在PermGen中的内存泄漏


很遗憾,不是这样的。这是一个使用Hibernate的高流量网站 - 因此有很多CGLIB类代理,因此需要大量的PermGen值。几天的正常运行并没有显示任何堆使用量的持续增长。我们最近解决了这个问题,我很快会发布我的答案。 - seanhodges

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接