一次12G堆dump的分析
背景
生产环境一个系统偶尔出现卡顿的情况,于是拿到线上环境的jvm配置和堆dump信息。
堆内存配置
堆内存配置分析
•堆的总内存是12G•年轻代478M•年老代11.5G•永久代最小512M,最大1G•年轻代与年老代的比=1:25
,这个比例也是很惊人的,默认比例是2,也就是三分天下,年轻代占一,年老代占二。•SurvivorRatio
是1024,代表Eden区
:一个Surivor区
=1024。所以From Space
和To Space
都只有43.75KB
。
为何会出现如此小的Survivor区呢,小的跟没有一样了,看参数发现配了这么个参数:-XX:MaxTenuringThreshold=0
,这个代表年轻代的对象经历多少次GC,如果还活着就会放到年老代,结果这儿配成了0,那意思就是只要在Minor GC后活着,就放到年老代。这样的话,Survivor区确实就没啥用了。
和调整参数的同事沟通,但是他们调整的原因是:
但是这样的话不就会出现年老代一直累积,累积到七八个G,然后来一把Full GC吗,本来很多对象是可以朝生暮死的,但是我们一直攒着,让它苟活于世。很容易导致Full GC时的长STW(stop the world)。
堆dump信息分析
通过MAT工具分析dump的堆信息,存在以下问题
1.unreachable object很多,占了4个G左右,有很多是由Artery框架生成的表单控件,由于在第一次MinorGC时还活着,就放到老年代了。可以考虑能否优化框架代码,对象重用。
2.缓存内容太多,动不动就是几十上百M。针对这些大缓存,需要考虑命中率,考虑LRU,减少对象。
3.hibernate用的太随意,产生了大量无用对象。4.字符串占用了两个多G,java9是提供了字符串压缩功能,可以节约1半的内存。
其他
•待后续改进后,再发布进展情况。•to be continued...
参考资料
•https://docs.oracle.com/javase/9/gctuning/concurrent-mark-sweep-cms-collector.htm#JSGCT-GUID-4CB5DCEB-FCBF-4A57-83A1-F2C47BF0B3D7
本文分享自微信公众号 - 程序员阿水(gh_124d28263603)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。