五、测试
5.1 测试代码:
public class TestGC { // 实现:不断的产生新的数据(对象),随机的去废弃对象(垃圾) public static void main(String[] args) throws Exception { List<Object> list = new ArrayList<>(); while (true){ int sleep = new Random().nextInt(100); if(System.currentTimeMillis() % 2 ==0){ //当前的时间戳,是偶数 list.clear(); }else{ //向List中添加1000个对象 for (int i = 0; i < 10000; i++) { Properties properties = new Properties(); properties.put("key_"+i,"value_"+System.currentTimeMillis()+i); list.add(properties); } } Thread.sleep(sleep); } } }
5.2 测试参数:
-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:+PrintGCDetails -Xmx256m
5.3 日志输出:
[GC pause (G1 Evacuation Pause) (young), 0.0027884 secs] [Parallel Time: 2.2 ms, GC Workers: 8] [GC Worker Start (ms): Min: 542.1, Avg: 542.1, Max: 542.2, Diff: 0.1] # 扫描根节点 [Ext Root Scanning (ms): Min: 0.1, Avg: 0.3, Max: 0.5, Diff: 0.4, Sum: 2.1] # 更新RS区域所消耗的时间 [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0] [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0] [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0] [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1] # 对象拷贝 [Object Copy (ms): Min: 1.6, Avg: 1.8, Max: 1.9, Diff: 0.4, Sum: 14.6] [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.3] [Termination Attempts: Min: 1, Avg: 5.5, Max: 7, Diff: 6, Sum: 44] [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.2] [GC Worker Total (ms): Min: 2.1, Avg: 2.1, Max: 2.2, Diff: 0.1, Sum: 17.2] [GC Worker End (ms): Min: 544.2, Avg: 544.2, Max: 544.2, Diff: 0.0] [Code Root Fixup: 0.0 ms] [Code Root Purge: 0.0 ms] [Clear CT: 0.1 ms] # 清空CardTable [Other: 0.5 ms] [Choose CSet: 0.0 ms] # 选取 CSet [Ref Proc: 0.4 ms] # 弱引用、软引用的处理耗时 [Ref Enq: 0.0 ms] # 弱引用、软引用的入队耗时 [Redirty Cards: 0.0 ms] [Humongous Register: 0.0 ms] # 大对象区域注册耗时 [Humongous Reclaim: 0.0 ms] # 大对象区域回收耗时 [Free CSet: 0.0 ms] [Eden: 12.0M(12.0M)->0.0B(13.0M) Survivors: 0.0B->2048.0K Heap: 12.0M(252.0M)->3282.5K(252.0M)] # 年轻代的大小统计 [Times: user=0.00 sys=0.00, real=0.00 secs]
五、对于G1垃圾回收器优化建议
年轻代大小:
避免使用 -Xmn选项或 -XX:NewRatio 等其他相关选项显示设置年轻代大小
固定年轻代的大小会覆盖暂停时间目标
暂停时间目标不要太过严苛
G1 GC 的吞吐量目标是 90% 的应用程序时间和 10%的垃圾回收时间
评估G1 GC的吞吐量时,暂停时间目标不要太严苛,目标太过严苛表示你愿意承受更多的垃圾回收开销,而这会直接影响到吞吐量
六、可视化GC日志分析工具
6.1 GC日志输出参数
前面通过 -XX:PrintGCDetails可以对GC日志进行打印,我们就可以在控制台查看,这样虽然可以查看GC的信息,但是并不直观,可以借助于第三方的GC日志分析工具进行查看
在日志打印输出设计到的参数如下:
-XX:+PrintGC:输出GC日志
-XX:+PrintGCDetails:输出GC的详细日志
-XX:+PrintGCTimeStamps:输出GC的时间戳(以基准的时间的形式)
-XX:+PrintGCDateStamps:输出GC的时间戳(以日期的形式,如: 2020-05-04T21:25.234+0800)
-XX:+PrintHeapAtGC:在进行GC的前后打印出堆的信息
-Xloggc:…/logs/gc.log 日志文件的输出路径
测试参数:
-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -Xmx256m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:E://test//gc.log
1
运行main 方法后,我们就可以在 E://test//gc.log下发现一个 gc.log 的日志文件:
6.2 GC Easy 可视化工具
GC Easy是一款在线可视化工具,易用、功能强大,可以通过GC日志分析进行内存泄露检测、GC暂停原因分析、JVM配置建议优化等功能,而且是可以免费使用的
网站地址:http://gceasy.io
上传gc.log后,点击Analyze,就可以查看日志报告了
JVM的各个分代区域分配的内存及使用峰值的内存
关键性能指标: 吞吐量及GC暂停平均时间、最大时间、各个时间段的比例
Throughput表示的是吞吐量
Latency表示响应时间
Avg Pause GC Time 平均GC时间
Max Pause GC TIme 最大GC时间
第一部分是Heap after GC,GC后堆的内存图,堆是用来存储对象的
第二部分是Heap before GC,这是GC前堆的使用率,可以看出随着程序的运行,堆使用率越来越高,堆被对象占用的内存越来越大。
第三部分是GC Duration Time,就是GC持续时间。从图中可以看到,发生Full GC的时间持续的比较短,而Young GC持续的时间比较长。图中横坐标表示GC发生的时间段,纵坐标表示的是GC持续时间。
表示的是GC回收掉的垃圾对象的内存大小。
GC Statistics
**Reclaimed Bytes(gb):**表示的是堆内存中Minor GC和Full GC回收垃圾对象的内存。
GC cumulative Time(ms):总计GC时间,包括Minor GC和Full GC,时间单位为ms。
GC Average Time(ms):GC平均时间,包括了Minor GC和Full GC。
总GC统计
MinorGC的统计
FullGC的统计
GC暂停程序的统计
七、结束语
到这里G1垃圾回收器就讲完了,感兴趣的小伙伴记得点赞关注,大家加油!