JVM——GC调优

JVM——GC调优

预备知识

需要掌握 GC 相关的 VM 参数,会基本的空间调整,这是最基本的东西。JVM调优是一个不断调整的过程,不能指望着一蹴而就。要不断调整相关参数,观察结果进行对比分析。还有就是,不同的垃圾收集器的JVM参数是不一样的,所以具体的GC调优要根据不同的收集器做调整。推荐看下Java关于收集器调优的官方文档:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/toc.html,

最快的 GC答案是不发生 GC。
查看 FullGC 前后的内存占用,考虑下面几个问题
1.数据是不是太多?

2.数据表示是否太臃肿?

3.是否存在内存泄漏?

新生代调优

新生代的特点:
所有的 new 操作的内存分配非常廉价
死亡对象的回收代价是零
大部分对象用过即死
Minor GC 的时间远远低于 Full GC

新生代越大越好吗?
答案是否定的,总内存是一定的,新生代大了,老年代就会小,就会发生Full GC 时间更长。

调优特点:
新生代能容纳所有【并发量 * (请求-响应)】的数据。
幸存区大到能保留【当前活跃对象+需要晋升对象】。
新生代晋升阈值配置得当,让长时间存活对象尽快晋升。

-XX:MaxTenuringThreshold=threshold(最大晋升阈值)
-XX:+PrintTenuringDistribution(打印幸存区不同年龄对象的详细信息)
例如:
Desired survivor size 48286924 bytes, new threshold 10 (max 10)

  • age 1: 28992024 bytes, 28992024 total :年龄为1 的占用内存
  • age 2: 1366864 bytes, 30358888 total :年龄为2的和年龄为1的占用内存
  • age 3: 1425912 bytes, 31784800 total:…

老年代调优

以 CMS 为例:
1.CMS 的老年代内存越大越好。因为如果当你Full GC 发生后,因为在CMS中垃圾回收是并发的,所以会产生浮动垃圾,当浮动垃圾特别多的时候就不会发生CMS Full GC,就会变成SerialOld GC 这样就会导致时间变得很长。
2.先尝试不做调优,如果没有 Full GC 那么已经内存可以满足,否则先尝试调优新生代。
3.观察发生 Full GC 时老年代内存占用,将老年代内存预设调大 1/4 ~ 1/3
-XX:CMSInitiatingOccupancyFraction=percent (当老年代的空间占用占老年代总内存的多少时,就发生Full GC)

调优案例

案例1 Full GC 和 Minor GC频繁

Minor GC频繁说明内存空间紧张,新生代中内存紧张后,会把对象晋升老年代的阈值降低,这样就会导致老年代中存在生命周期很短的对象,触发了老年代的Full GC。
增大新生代内存空间大小,使晋升阈值增大,这样老年代中对象就会变少,Full GC就不会频繁。

案例2 请求高峰期发生 Full GC,单次暂停时间特别长 (CMS)

先查看GC日志,看看那个时间较长。发现重新标记时间较长,因为重新标记是需要扫描整个堆内存(新生代和老年代),可以在重新标记之前,在新生代发生一次垃圾回收,这样重新标记时查找的对象就会变少。

案例3 老年代内存充裕情况下,发生 Full GC (CMS jdk1.7)

因为在1.7是永久代,内存不足会导致Full GC 。解决办法:增大元空间的初始值和最大值。
而在1.8是元空间,是由系统直接管理,内存很充裕。

你可能感兴趣的:(JVM,jvm,java,垃圾回收)