知识库

Loading

0 评论 / 0 点赞 / 118 阅读  最佳实践 最后更新: 2022-08-15 作者: 飞致云 总字数: 1563

为什么要介绍这个工具?

GC日志是一个很重要的数据,它准确记录了每一次的GC的执行时间和执行结果,通过分析GC日志可以优化堆设置和GC设置,或者改进应用程序的对象分配模式。

GCEasy是什么?

业内首款借助机器学习技术引导的垃圾回收日志分析工具。GCeasy 内置有智能功能,可自动检测 JVM 和 Android GC 日志中的问题并推荐解决方案,推荐解决方案是付费功能。

GCEasy怎么使用?让我们来看个例子

  1. 首先要开启应用GC日志,关于开启GC日志命令有很多可选参数,这里不细讲,可以参考:https://blog.csdn.net/lazycheerup/article/details/100917193
    本次使用以下命令演示:
    java -XX:+PrintGCDetails -Xloggc:/opt/ard-user-gc-%t.log -jar spring-boot-demo-0.0.1-SNAPSHOT.jar
    image-1660542283245
    image-1660542660991
  2. 将应用产生的GC上传到https://gceasy.io/
    image-1659952009736
    点击“分析”,等待分析结果。
    image-1659952064755
  3. GC分析报告支持下载和分享连接。
    image-1659952125092

GC日志报告包含哪些指标分析?

image-1659952222951
image-1659952271326
image-1659952322782
image-1659952331986
image-1659952341908
image-1659952354207
image-1659952362059
image-1659952369577
image-1659952376758
image-1659952384567

常见的一些GC问题

对象过早晋升

一、现象:

  • 老年代使用率增长过快,每次Full GC后老年代使用率呈现断崖式下跌,Minor GC 和 Full GC都比较频繁。
  • 老年代空间占用量统计(通过gc日志统计):
    image-1660542880443
    二、影响:
  • Young GC 频繁,总的吞吐量下降。
  • Full GC 频繁,可能会有较大停顿。
    三、原因:
    年轻代(主要是eden区)过小:
  • eden区无法容纳足够多的年轻对象,造成young gc的次数增加。
  • 本应该在年轻代就回收的对象却晋升到了老年代,加快了老年代的占用速度,造成full gc的次数增加。
    四、优化:
  • 增大新生代空间,降低minor gc和major gc的频率,减少系统STW的时间、提高系统的吞吐量。

对象晋升失败

一、场景:

  • young gc过程中,To Survivor空间不足以放下eden + from Survivor中存活的对象,故这些存活的对象只能尝试着晋升到老年代中,若此时老年代的内存也不足以放下这些对象,则晋升失败(promotion failed),此时,老年代会进行full gc。
    二、优化:
  • 适当地调大Survivor空间,尽量避免朝生夕灭的对象进入老年代。
  • 使用标记整理算法收集,及时整理老年代中的内存碎片,避免因内存碎片太多导致大对象晋升失败:
  1. 开启老年代内存压缩:-XX:UseCMSCompactAtFullCollection
  2. 每次cms gc时都进行内存压缩:XX:CMSFullGCBeforeCompaction=0

并发收集失败

一、场景:

  • 场景1:CMS GC期间,业务线程将对象放到老年代,若此时老年代空间不足,则会导致CMS并发收集失败(Concurrent Mode Failure)。
  • 场景2:CMS GC期间,若某次young gc过程中发生了promotion failed,则也会导致CMS并发收集失败。
  • CMS并发收集失败发生后,由于老年代空间不足,需要尽快回收老年代里面的不再被使用的对象,这时jvm会停止所有的应用线程,同时终止CMS收集,直接进行Serial Old来收集。
    二、现象:
  • stop the world持续时间比较长,系统持续(十几秒甚至几分钟)无响应。
    三、优化:
  • 在业务低峰时段提前触发full gc。
    没有开启-XX:+DisableExplicitGC的前提下调用System.gc()就会发生FullGC
  • 降低触发CMS GC的阈值,保障老年代有足够的空间。
    开启根据阈值触发CMS GC开关:-XX:+UseCMSInitiatingOccupancyOnly
    设置触发CMS GC的阈值:-XX:CMSInitiatingOccupancyFraction=xx (默认是92)
文章目录
其他资源