我有一个二进制文件,其中包含一个短字符串列表,该列表在启动时加载,并作为从字符串到protobuf(包含字符串..)的Map存储在内存中。(不理想,但由于遗留问题,很难更改该设计)最近,该列表已从~ 2 M项增长到~ 20 M项,导致它在构建Map时失败。
首先我得到了OutOfMemoryError: Java heap space
。
当我使用xms和xmx增加堆大小时,我们遇到了GC overhead limit exceeded
。
在Linux 64位机器上运行,具有15 GB可用内存和以下JVM参数(我将RAM增加到10 G-〉15 G,堆标志增加到6000 M-〉9000 M):-Xms9000M -Xmx9000M -XX:PermSize=512m -XX:MaxPermSize=2018m
这个二进制文件做了很多事情,并为实时流量服务,所以我不能承受它偶尔被卡住。
编辑:我最终去做了一件显而易见的事情,那就是修复代码(从HashMap改为ImmutableSet)并添加更多RAM(-Xmx 11000 M)。
1条答案
按热度按时间xiozqbni1#
我正在寻找一个临时的解决方案,如果这是可能的,直到我们有一个更可扩展的。
首先,您需要确定“OOME:超出GC开销限制”是由于堆处于以下状态:
通过打开并检查GC日志,使用操作系统级别的监视工具来检查是否存在过多的分页负载,您应该能够区分这两种情况。(在检查分页级别时,还要检查问题是否是由于JVM和另一个占用大量内存的应用程序之间的RAM竞争造成的。)
如果堆太小,试着把它变大。如果太大,把它变小。如果你的系统同时出现这两种症状...那你就有大问题了。
您还应该检查JVM是否启用了“compressed oops”,因为这将减少JVM的内存占用量。
-XshowSettings
选项列出了JVM启动时生效的设置。如果压缩oops已禁用,请使用-XX:+UseCompressedOops
启用它们。(You可能会发现压缩的oops默认是启用的,但值得检查一下。这将是一个简单的修复...)
如果以上都不起作用,那么你唯一的快速解决办法就是获得更多的RAM。
但很明显,真实的的解决方案是重新设计代码,这样就不需要庞大的(并且随着时间的推移而不断增加的)内存中数据结构。