前言
- 无意中搞出来的 JVM 案例,正好用作分析使用。
步骤
- Java 代码
- 执行命令
- jstat 500ms 打印一次获取日志数据
- 日志分析
- 日志变化不明显, 继续监控获取日志,找到老年代增长率。
- 日志分析,每次 Young GC 转移的对象大小
- 优化后执行命令
- 调优后执行日志
- 优化结果(重要)
Java 代码
public class Demo {
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 5000; i++) {
byte[] array1 = new byte[1 * 1024 * 1024];
byte[] array2 = new byte[1 * 1024 * 1024];
byte[] array3 = new byte[1 * 1024 * 1024];
byte[] array4 = new byte[1 * 1024 * 1024];
byte[] array5 = new byte[1 * 1024 * 1024];
byte[] array6 = new byte[1 * 1024 * 1024];
array1 = null;
array2 = null;
array3 = null;
array4 = null;
array5 = null;
array6 = null;
Thread.sleep(1000);
}
}
}
执行命令
nohup java -XX:NewSize=10M -XX:MaxNewSize=10M -XX:InitialHeapSize=20M -XX:MaxHeapSize=20M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:PretenureSizeThreshold=3145728 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log -jar jvm-demo-1.0.0.jar &
jstat 500ms 打印一次获取日志数据
[root@localhost jvm]
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1024.0 1024.0 0.0 0.0 8192.0 3232.3 10240.0 6436.1 4864.0 2903.2 512.0 313.2 93 0.052 95 0.095 0.147
1024.0 1024.0 0.0 0.0 8192.0 2208.3 10240.0 4383.9 4864.0 2903.2 512.0 313.2 94 0.052 96 0.097 0.149
1024.0 1024.0 0.0 0.0 8192.0 2208.3 10240.0 4383.9 4864.0 2903.2 512.0 313.2 94 0.052 96 0.097 0.149
1024.0 1024.0 0.0 0.0 8192.0 1024.0 10240.0 5410.0 4864.0 2903.2 512.0 313.2 95 0.053 98 0.098 0.152
1024.0 1024.0 0.0 0.0 8192.0 1024.0 10240.0 5410.0 4864.0 2903.2 512.0 313.2 95 0.053 98 0.098 0.152
1024.0 1024.0 0.0 0.0 8192.0 7328.4 10240.0 5410.0 4864.0 2903.2 512.0 313.2 95 0.053 98 0.098 0.152
1024.0 1024.0 0.0 0.0 8192.0 7328.4 10240.0 5410.0 4864.0 2903.2 512.0 313.2 95 0.053 98 0.098 0.152
1024.0 1024.0 0.0 0.0 8192.0 6304.3 10240.0 287.9 4864.0 2903.2 512.0 313.2 96 0.053 100 0.101 0.154
1024.0 1024.0 0.0 0.0 8192.0 6304.3 10240.0 287.9 4864.0 2903.2 512.0 313.2 96 0.053 100 0.101 0.154
1024.0 1024.0 0.0 0.0 8192.0 5280.3 10240.0 1313.9 4864.0 2903.2 512.0 313.2 97 0.054 100 0.101 0.154
1024.0 1024.0 0.0 0.0 8192.0 5280.3 10240.0 1313.9 4864.0 2903.2 512.0 313.2 97 0.054 100 0.101 0.154
1024.0 1024.0 0.0 0.0 8192.0 4256.3 10240.0 3362.0 4864.0 2903.2 512.0 313.2 98 0.054 100 0.101 0.155
1024.0 1024.0 0.0 0.0 8192.0 4256.3 10240.0 3362.0 4864.0 2903.2 512.0 313.2 98 0.054 100 0.101 0.155
1024.0 1024.0 0.0 0.0 8192.0 3232.3 10240.0 6436.1 4864.0 2903.2 512.0 313.2 99 0.055 101 0.101 0.156
日志分析
- Survivor 一直没有使用,推测:说明 Youong GC 新生代垃圾回收干净,或者都转移到了 老年代。
- Eden 区一直有变化,老年代也一直有变化,说明进行了垃圾回收, Survivor 分区 1M 的 50% 放不下,都转移到老年代了。
日志变化不明显, 继续监控获取日志,找到老年代增长率。
- 找到合适的那部分日志,截取出来。
[root@localhost jvm]
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1024.0 1024.0 0.0 0.0 8192.0 7328.4 10240.0 5410.0 4864.0 2903.2 512.0 313.2 437 0.217 451 0.445 0.662
1024.0 1024.0 0.0 0.0 8192.0 0.0 10240.0 287.9 4864.0 2903.2 512.0 313.2 438 0.217 453 0.447 0.664
1024.0 1024.0 0.0 0.0 8192.0 6304.3 10240.0 287.9 4864.0 2903.2 512.0 313.2 438 0.217 453 0.447 0.664
1024.0 1024.0 0.0 0.0 8192.0 6304.3 10240.0 287.9 4864.0 2903.2 512.0 313.2 439 0.218 453 0.447 0.665
1024.0 1024.0 0.0 0.0 8192.0 5280.3 10240.0 1313.9 4864.0 2903.2 512.0 313.2 439 0.218 454 0.448 0.666
1024.0 1024.0 0.0 0.0 8192.0 0.0 10240.0 3362.0 4864.0 2903.2 512.0 313.2 440 0.219 454 0.448 0.667
1024.0 1024.0 0.0 0.0 8192.0 4256.3 10240.0 3362.0 4864.0 2903.2 512.0 313.2 440 0.219 454 0.448 0.667
1024.0 1024.0 0.0 0.0 8192.0 0.0 10240.0 6436.1 4864.0 2903.2 512.0 313.2 441 0.220 455 0.448 0.668
1024.0 1024.0 0.0 0.0 8192.0 3232.3 10240.0 6436.1 4864.0 2903.2 512.0 313.2 441 0.220 455 0.448 0.668
1024.0 1024.0 0.0 0.0 8192.0 0.0 10240.0 4383.9 4864.0 2903.2 512.0 313.2 442 0.220 456 0.450 0.670
1024.0 1024.0 0.0 0.0 8192.0 2208.3 10240.0 4383.9 4864.0 2903.2 512.0 313.2 442 0.220 456 0.450 0.670
1024.0 1024.0 0.0 0.0 8192.0 0.0 10240.0 9506.1 4864.0 2903.2 512.0 313.2 443 0.221 457 0.450 0.671
1024.0 1024.0 0.0 0.0 8192.0 1024.0 10240.0 5410.0 4864.0 2903.2 512.0 313.2 443 0.221 458 0.451 0.672
1024.0 1024.0 0.0 0.0 8192.0 1024.0 10240.0 5410.0 4864.0 2903.2 512.0 313.2 443 0.221 458 0.451 0.672
1024.0 1024.0 0.0 0.0 8192.0 7328.4 10240.0 5410.0 4864.0 2903.2 512.0 313.2 443 0.221 458 0.451 0.672
1024.0 1024.0 0.0 0.0 8192.0 0.0 10240.0 287.9 4864.0 2903.2 512.0 313.2 444 0.221 461 0.454 0.675
日志分析,每次 Young GC 转移的对象大小
- 第一次:1313.9 - 287.9 大约 1024 = 1M
- 第二次:3362.0 - 1313.9 大约 2048 = 2M
- 第三次:6436.1 - 3362.0 大约 3072 = 3M
- 再然后第四次 Young GC 后,触发了 Full GC
- 每次最大可能有 3 M 存活,对于总内存 20 M 来说,应该要加机器。
- 先不加机器调优:20M内存,老年代设置为4M,Eden9M,Survivor两个7M(使用率98%)。
- 3次 Youong GC 就会有一次 Full GC,只能尽量这样处理,实在是分配资源不够。
优化后执行命令
nohup java -XX:NewSize=16M -XX:MaxNewSize=16M -XX:InitialHeapSize=20M -XX:MaxHeapSize=20M -XX:SurvivorRatio=6 -XX:MaxTenuringThreshold=15 -XX:TargetSurvivorRatio=98 -XX:PretenureSizeThreshold=3145728 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log -jar jvm-demo-1.0.0.jar &
调优后执行日志
[root@localhost jvm]
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
2048.0 2048.0 1024.0 0.0 12288.0 11509.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 18 0.014 13 0.010 0.024
2048.0 2048.0 1024.0 0.0 12288.0 11509.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 18 0.014 13 0.010 0.024
2048.0 2048.0 0.0 0.0 12288.0 6389.8 4096.0 318.3 4864.0 2903.5 512.0 313.2 19 0.014 13 0.010 0.025
2048.0 2048.0 0.0 0.0 12288.0 6389.8 4096.0 318.3 4864.0 2903.5 512.0 313.2 19 0.014 13 0.010 0.025
2048.0 2048.0 0.0 1024.0 12288.0 11509.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 19 0.014 13 0.010 0.025
2048.0 2048.0 0.0 1024.0 12288.0 11509.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 19 0.014 13 0.010 0.025
2048.0 2048.0 0.0 0.0 12288.0 6389.8 4096.0 318.3 4864.0 2903.5 512.0 313.2 20 0.015 13 0.010 0.025
2048.0 2048.0 0.0 0.0 12288.0 6389.8 4096.0 318.3 4864.0 2903.5 512.0 313.2 20 0.015 13 0.010 0.025
2048.0 2048.0 1024.0 0.0 12288.0 11509.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 20 0.015 13 0.010 0.025
2048.0 2048.0 1024.0 0.0 12288.0 11509.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 20 0.015 13 0.010 0.025
2048.0 2048.0 0.0 0.0 12288.0 6389.8 4096.0 318.3 4864.0 2903.5 512.0 313.2 21 0.016 13 0.010 0.027
2048.0 2048.0 0.0 0.0 12288.0 6389.8 4096.0 318.3 4864.0 2903.5 512.0 313.2 21 0.016 13 0.010 0.027
2048.0 2048.0 0.0 1024.0 12288.0 11509.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 21 0.016 13 0.010 0.027
2048.0 2048.0 0.0 0.0 12288.0 0.0 4096.0 318.3 4864.0 2903.5 512.0 313.2 22 0.017 13 0.010 0.027
2048.0 2048.0 0.0 0.0 12288.0 6389.8 4096.0 318.3 4864.0 2903.5 512.0 313.2 22 0.017 13 0.010 0.027
2048.0 2048.0 0.0 0.0 12288.0 6389.8 4096.0 318.3 4864.0 2903.5 512.0 313.2 22 0.017 13 0.010 0.027
2048.0 2048.0 1024.0 0.0 12288.0 11509.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 22 0.017 13 0.010 0.027
2048.0 2048.0 0.0 0.0 12288.0 0.0 4096.0 318.3 4864.0 2903.5 512.0 313.2 23 0.017 13 0.010 0.028
2048.0 2048.0 0.0 0.0 12288.0 6389.8 4096.0 318.3 4864.0 2903.5 512.0 313.2 23 0.017 13 0.010 0.028
2048.0 2048.0 0.0 1024.0 12288.0 11509.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 23 0.017 13 0.010 0.028
2048.0 2048.0 0.0 1024.0 12288.0 11509.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 23 0.017 13 0.010 0.028
2048.0 2048.0 0.0 0.0 12288.0 0.0 4096.0 318.3 4864.0 2903.5 512.0 313.2 24 0.018 13 0.010 0.028
2048.0 2048.0 0.0 0.0 12288.0 6389.8 4096.0 318.3 4864.0 2903.5 512.0 313.2 24 0.018 13 0.010 0.028
2048.0 2048.0 0.0 0.0 12288.0 6389.8 4096.0 318.3 4864.0 2903.5 512.0 313.2 24 0.018 13 0.010 0.028
2048.0 2048.0 1024.0 0.0 12288.0 11509.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 24 0.018 13 0.010 0.028
2048.0 2048.0 0.0 0.0 12288.0 6389.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 25 0.018 13 0.010 0.029
2048.0 2048.0 0.0 0.0 12288.0 6389.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 25 0.018 13 0.010 0.029
2048.0 2048.0 0.0 0.0 12288.0 6389.9 4096.0 318.3 4864.0 2903.5 512.0 313.2 25 0.018 13 0.010 0.029
优化结果(重要)
- 调优后效果明显,老年代没有对象进入,新生代垃圾回收后对象的都能存放下了。
- 注意:这里面有取巧的痕迹,因为是自己指定写的代码,如果再生产中,那么就要使用高峰期的指标作为参照。
- 最好的方式还是要升级机器配置才行,机器压力太大,万一出了生产问题就是大问题了。