我有一个二进制文件,其中包含一个短字符串列表,该列表在启动时加载并作为从字符串到 protobuf (包含字符串..)的映射存储在内存中。 (不理想,但由于遗留问题很难改变设计)
最近,该列表已从约 2M 条目增长到约 20M 条目,导致构建地图时失败。
首先我得到了OutOfMemoryError: Java heap space
.
当我使用 xms 和 xmx 增加堆大小时,我们遇到了GC overhead limit exceeded
.
在具有 15GB 可用内存和以下 JVM 参数的 Linux 64 位机器上运行(我增加了 RAM 10G->15G 和堆标志 6000M -> 9000M):
-Xms9000M -Xmx9000M -XX:PermSize=512m -XX:MaxPermSize=2018m
这个二进制文件做了很多事情并且正在服务实时流量,所以我不能承受它偶尔被卡住的情况。
编辑:我最终做了一件显而易见的事情,即修复代码(从 HashMap 更改为 ImmutableSet)并添加更多 RAM (-Xmx11000M)。
如果可能的话,我正在寻找一种临时解决方案,直到我们有一个更具可扩展性的解决方案。
首先,您需要弄清楚“OOME:超出GC开销限制”是否是由于堆引起的:
您应该能够通过打开和检查 GC 日志并使用操作系统级别的监视工具检查是否存在过多的分页负载来区分这两种情况。 (在检查分页级别时,还要检查问题是否不是由于 JVM 与其他内存消耗大的应用程序之间的 RAM 竞争造成的。)
如果堆太小,请尝试将其增大。如果太大,请将其缩小。如果您的系统同时出现这两种症状……那么您就有大问题了。
您还应该检查 JVM 是否启用了“压缩 oops”,因为这将减少 JVM 的内存占用。这-XshowSettings
选项列出了 JVM 启动时生效的设置。使用-XX:+UseCompressedOops
如果压缩 oops 被禁用,则启用它们。
(您可能会发现默认情况下启用压缩 oops,但值得检查。这将是一个简单的修复...)
如果上述方法都不起作用,那么唯一的快速解决办法就是获得更多内存。
但显然,真正的解决方案是重新设计代码,这样您就不需要巨大的(并且随着时间的推移而增加)内存数据结构。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)