JVM个人总结(五)
(个人对黑马程序员JVM完整教程总结,原视频地址https://www.bilibili.com/video/BV1yE411Z7AP)
垃圾回收调优
查看虚拟机运行参数:
-XX: +PrintFlagsFinal -version | findstr “GC”
调优领域
- 内存
- 锁竞争
- cpu占用
- io
调优目标
- 低延迟 or 高吞吐量,选择合适的回收器
- CMS,G1,ZGC
- ParallelGC
- Zing
最快的GC是不发生GC
查看Full GC前后的内存占用,考虑下面的问题:
- 数据是不是太多
- 数据表示是否太臃肿
- 对象图 对象大小
- 是否存在内存泄漏
- 软引用
- 弱引用
- 考虑第三方的缓存实现
新生代调优
新生代特点:
- 所有的new操作的内存分配非常廉价
- TLAB thread-local allocation buffer 作用:让每个线程的私有的伊甸园线程来进行对象的分配(这样多个线程创建对象时,也不会对内存占用造成干扰)
- 死亡对象的回收代价是零
- 大部分对象用过即死
- Minor GC 的时间远远低于 Full GC
(新生代的调优空间更大于老年代)
设置新生代的大小:
Oracle官方建议新生代大小在 堆 的25% ~ 50%之间
- 幸存区大到能保存【当前活跃对象+需要晋升对象】
- 幸存区晋升阈值配置得当,让长时间存活对象尽快晋升
老年代调优
以CMS为例
- CMS的老年代内存越大越好
- 先尝试不做调优,如果没有Full GC 那么已经可以了, 否则先尝试调优新生代
- 观察发生Full GC 时老年代内存占用,将老年代内存预设调大 1/4 ~ 1/3
- -XX:CMSInitiatingOccupancyFraction=percent
案例分析
案例1 Full GC 和 Minor GC 频繁
分析:GC频繁说明空间紧张,新生代空间紧张导致幸存区晋升阈值降低,很多低生命周期的对象也被晋升到老年代,导致老年代Full GC频繁
解决方案:查看各空间内存大小,调大新生代内存大小
案例2 请求高峰期发生Full GC,单次暂停时间特别长(CMS)
分析:查看日志,查找哪个阶段耗费时间过长
解决方案:重新标记阶段耗时过长:在重新标记发生之前先对新生代的对象进行一次垃圾清理(-XX:+CMSScavengeBeforeRemark)