问题 java.lang.OutOfMemoryError:压缩类空间


我们正在运行java-8-oracle。

我们六个月前搬到了java8。

在过去的几天里,我们不时收到OOME,但我们无法识别或重现问题。

当我们执行对服务器(tomcat)的调用时,我们在stacktrace上得到这个错误:

java.lang.OutOfMemoryError: Compressed class space

重新启动服务器可以解决问题。对其他服务器的相同调用也起作用,对另一个类型的另一个调用也是如此。

在gc.log上查看时,我们看到:

2015-05-27T16:05:42.991+0000: 98774.440: [Full GC (Last ditch collection) 98774.440: [CMS: 575745K->575330K(3495936K), 0.8687777 secs] 575745K->575330K(4107008K), [Metaspace: 97940K->97940K(1396736K)], 0.8696093 secs] [Times: user=0.95 sys=0.00, real=0.88 secs]
2015-05-27T16:05:55.486+0000: 98786.935: [Full GC (Metadata GC Threshold) 98786.935: [CMS: 573414K->578735K(3495936K), 0.9372859 secs] 925046K->578735K(4107008K), [Metaspace: 99428K->99428K(1396736K)], 0.9386626 secs] [Times: user=1.01 sys=0.00, real=0.94 secs]

jstat -gc 收益:

 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
87296.0 87296.0  0.0   3151.4 523776.0 148284.4 3495936.0   574868.5  1395640.0 98066.3 1048576.0 11339.1  12165  636.851  223   116.957  

753.808

我在jstat日志或gc日志中都没有看到任何内存问题。

试着跑 jmap -clstats 挂起:

Attaching to process ID 5110, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.25-b02
finding class loader instances ..

3652
2018-05-28 15:51


起源

使用哪个Xms和Xmx交换机可以启动JVM?我建议您使用visualvm或类似工具来更好地了解和了解JVM大小的设置方式。或者使用Eclipse Memory Analyzer。目前您可以尝试使用-XX:CompressedClassSpaceSize来增加压缩类空间。要更好地分析问题,您应该将JVM设置为OOME上的堆转储。 - Marged
在什么时间段之后你会看到这个例外?你尝试过增加CompressedClassSpace吗?例如:-XX:CompressedClassSpaceSize = 1g?如果你再次看到问题,但经过一段较​​长的时间后,你似乎有某种内存泄漏。 - David George
@DavidG - 2天前第一次遇到其中一个服务器(我们没有部署新版本)。重新启动服务器,而不是仅在其中一台服务器中12小时后再次看到它。压力负载dosnt有助于重现。压缩尺寸几乎保持不变,并且不接近1G,这是默认值。 - user1236097
这可能是一个JVM错误。一直在进行中 hotspot-gc-dev讨论 有类似症状的问题。尝试 调音 Metaspace收缩政策。 - apangin


答案:


我们遇到了类似的问题。不幸的是,heapdumps不会帮助你,因为类不在堆中而是在本机内存中。在JVM设置中启用这些以对加载的类进行故障排除:

-XX:+ PrintGCDetails -XX:+ TraceClassUnloading -XX:+ TraceClassLoading

在我们的例子中,问题是JAXBContext.newInstance不是单身人士。

祝你好运, 阿尔伯特


8
2018-05-17 10:22





使用压缩的oops和压缩类指针,由于必要的指针修改,类的可用空间受到限制。在你的情况下1GB。

这是很多类,所以这可能表明你的应用程序中的某些东西正在创建很多类而且从不发布它们。应用程序重装可能吗?

如果你确定你的应用程序只需要那么多的内存,你可以尝试通过限制来实现限制 -XX:CompressedClassSpaceSize=... 或通过禁用压缩类指针 -XX:-UseCompressedClassPointers

请注意,默认情况下压缩类空间+压缩堆(+一些开销)不能超过32GB。虽然,AIUI,改变对象对齐可以进一步突破这个限制。

否则你应该使用heapdump并分析保存在已加载类中的内容。


5
2018-05-28 16:13



您可以在jstat日志中看到CCSU是1048576.0,CCSU是11339.1。 - user1236097
可能是碎片?我认为课堂空间不会被压缩。虽然这样一个巨大的因素是奇怪的,即使它是碎片化的。此外,我认为你已经离开了一个专栏,但仍然存在差异。 - the8472
你可以运行它来查看列中是否有错:echo“S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT \ n 87296.0 87296.0 0.0 3151.4 523776.0 148284.4 3495936.0 574868.5 1395640.0 98066.3 1048576.0 11339.1 12165 636.851 223 116.957 753.808“|列-t - user1236097
你是对的。很奇怪。仍然,尝试这些选项,并在@Marged建议的OOME上启用堆转储。至少应该有助于进一步诊断。 - the8472