这些年来,我们一直密切关注以OutOfMemoryError消息的不同形式打包的问题。 通过专门的服务(例如Google警报),每天就特定关键字的新问题进行摘要,使我们对应用程序因日志中的java.lang.OutOfMemoryError失败而出现的情况有了一个很好的了解。
面临问题的人们往往会陷入细分市场,因此我决定对一些更有趣的角色进行一些描述。
自学成才的外科医生 。 这些家伙现在真正具有创造力,我绝对必须为此赞扬他们。 当遇到意外的错误消息时,他们提出了很多解释为什么可能发生此特定错误。 并立即解决该问题。
我已经多次看到以下所有内容,以至于我什至失去了计数。 我只能保证这些例子既真实又可怕:
- “即使我购买了16G的额外RAM,我仍然收到OutOfMemoryError错误”。 好吧,与其增加-Xmx,对于许多人来说,最明显的解决方案似乎是转向疯狂购物。
- “我的日志中遇到一个OutOfMemoryError,我发现一个.class文件的长度超过1500行。 摆脱掉消息,我的类文件必须有多小”。 如何获得类文件中的行数与堆空间用尽之间的相关性,这超出了我的范围,但是我想这种疯狂的做法是可行的。
- “我从使用java.util.Vectors切换到java.util.ArrayList,花了一个月的时间来重构我的应用程序,但仍然出现OutOfMemoryError”。 好吧,对您有好处,Vectors如此1999年。但同样,如果您不知道是什么导致疾病的原因,为什么要治愈患者?
这个名单可能永远持续下去。 令我感到好奇的是-当软件开发人员的行为举止如此时-我下次还要去看医生时是否还应该格外小心?
配置H2x0rz 。 如果JVM配置中有一个参数,则必须对其进行调整。 这似乎是该特定人群的唯一真理。 确实,Oracle JVM工程师推荐的默认值有任何意义的机会是什么。 结果? 应用程序启动时的最小堆太大,线程优先级混乱,使用期限极低的使用区域或不合适的和/或实验性的GC算法。
不要误会我的意思,如果您知道自己在做什么,并且正在根据实际测量结果进行微调,那就继续吧。 通常,这些类型的用户从某个地方继承了“正确的配置选项集”,并且现在将相同的-XX参数集应用于那里看到的每个JVM。 求你了 您上次面对的具有高度事务性的Web应用程序与您现在唾手可得的数据繁忙的批处理作业完全不同。
数据激增的受害者 。 这些家伙多年来一直在构建和运行业务应用程序而没有重大性能问题。 然后,雷电击中该应用程序在日志文件中出现OutOfMemoryErrors的情况下死在地面上。 通过执行一次将太多数据一次加载到内存中的操作,某些用户突然能够将整个应用程序运行到地面。
无论是由于业务良好而引起的,还是客户数量刚刚增长超过一定的魔点,还是公司收购并合并了一个使数据量增加一倍的竞争对手,效果都是一样的。
可以通过应用许多众所周知的工具和技术来解决这样的情况,当它们被识别时。 您可以推迟数据加载,小批量处理操作或更改负责存储此数据的数据结构-由您决定。 这些解决方案中的许多解决方案都非常合适。
但是,在这种情况下,我们看到的是将问题隐藏在增大的堆大小下。 通过增加配置中的-Xmx确实可以逃脱OutOfMemoryError,但是您仍然经常对用户造成伤害。 大型操作仍需要很长时间才能完成,因此,由于增加的延迟而使用户烦恼。 更糟糕的是,增加堆时,通常会导致GC暂停跨越到无法忍受的长度。
我的世界 如果我必须选择一个负责内存泄漏的应用程序,那就是Minecraft。 多年来,我很可能看到成千上万沮丧的9岁儿童被迫处理堆配置。
快速搜索可以发现问题的严重性,对于那些考虑发布基于Java的桌面软件的人来说,我想这是一个很好的案例研究。
如果您不觉得自己属于所列的任何组,那就好。 您是务实的工程师之一,他们在通过总结得出结论之前,通过仔细研究因果关系来为自己的Craft.io感到自豪。
翻译自: https://www.javacodegeeks.com/2014/02/outofmemoryerror-solution-antipatterns.html