- SerialGC
- 新生代内存不足时- minor gc
- 老年代内存不足时- full gc
- ParallelGC
- 新生代内存不足时- minor gc
- 老年代内存不足时- full gc
- CMS
- 新生代内存不足 minor gc
- 老年代内存不足时, 并发失败才会出现full gc
- G1
- 新生代内存不足时 minor-gc
- 老年代内存不足时,当新产生的垃圾速率大于老年代垃圾回收速率,才会进行full gc
Full GC可能出发的时间
- 老年代空间不足
- 元空间(metadata) 空间不足, 参考 Metaspace引起的FullGC问题排查过程及解决方案 - 知乎 (zhihu.com)
- Young GC对象进入老年代,引发Full GC,每次Young GC后不断有对象进入老年代,或老年代担保机制引发提前Full GC, 其实根本原因还是对象进入老年代,造成老年代空间被占满,无法分配给新到来的对象空间,从而引发Full GC
问题分析:
1、如果每次gc之后剩余的空间不大,说明有一部分顽固对象一直没法被回收,导致可用内存变少。这种情况下很容易后续出现oom,比如说一次大对象的申请.
2、如果每次gc之后剩余的空间比较大,意味着大部分对象都被清理了,但是系统又在频繁的full gc,说明很快老年代又会涌入大量对象。这个时候就应该检查下jvm的参数配置,很有可能是新生代设置的太小了,导致很多应该在minor gc阶段就清理出去的对象留到了老年代,这种可能性是最大的
fullgc 还需要考虑的问题
- 数据是否太多(select * from table_a)
- 数据表是否太臃肿(对象图,对象大小,基本类型的使用)
- 是否有内存泄漏,尽量不要用static 做一些缓存
内存调优:
新生代:
- 所有的new操作的内存分配非常廉价
- TLAB thread-local allocation buffer
- 死亡对象的回收代价是0
- 大部分对象用过即死
- Minor gc的时间远低于Full gc
方法:-Xmn
- 内存大小与吞吐量之间的最佳点。内存尽可能大
- 新生代能容纳所有的【并发量*(请求-响应)】数据
- 例如 并发量为1000, 请求+响应为512k, 则新生代理论应为1000 * 512 = 521mb
- 幸存区大到可以保留所有幸存的对象【当前幸存+需要晋升对象】
4 晋升阈值配置得当,让长时间存活的对象尽快晋升
-XX:MaxTenuringTheshold=
-XX:+PrintTenuringDistribution
CMS老年代调优
- CMS的老年代内存越大越好
- 先尝试不做调优,如果没有full gc,那就已经很不错了。先新生代调优
- 观察发生full gc老年代内存占用, 将内存预设值调大 1/4- 1/3
-XX:CMSInitiatingOccupancyFraction=percent, percent值越低,老年代触发垃圾回收时间越早