JVM GC Log的分析

本文通过示例代码和JVM启动参数,详细解析了JVM垃圾回收日志的生成与分析过程,包括GC触发原因、堆空间使用情况及各代区域的分配与回收细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

示例代码

public class Test {
    public static void main(String[] args) {
        // 1M 大小
        int size = 1024 * 1024;

        // 构建原生数据类型的数组
        byte[] allocate1 = new byte[2 * size];
        byte[] allocate2 = new byte[2 * size];
        byte[] allocate3 = new byte[3 * size];
        byte[] allocate4 = new byte[3 * size];
    }
}

指定运行程序的JVM启动参数

在这里插入图片描述
JVM启动参数说明:

-verbose:gc,表示输出详细的垃圾回收的日志
-Xms20M,堆初始大小
-Xmx20M,堆的最大大小,通常与初始大小设置成一样,防止出现jvm内存的抖动情况
-Xmn10M,表示堆空间中,指定新生代大小为10M
-XX:+PrintGCDetails,表示打印GC的详情
-XX:SurvivorRatio=8,表示Eden空间与Survivor空间的比例是8:1,
                     由于指定了新生代的空间是10M,所以这里的Eden空间是8M,2个Survivor空间分别占用1M大小

执行结果分析

[GC (Allocation Failure) [PSYoungGen: 6779K->936K(9216K)] 6779K->5040K(19456K), 0.0029926 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 9216K, used 7401K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 78% used [0x00000000ff600000,0x00000000ffc507d8,0x00000000ffe00000)
  from space 1024K, 91% used [0x00000000ffe00000,0x00000000ffeea020,0x00000000fff00000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 10240K, used 4104K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 40% used [0x00000000fec00000,0x00000000ff002020,0x00000000ff600000)
 Metaspace       used 3413K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 369K, capacity 388K, committed 512K, reserved 1048576K

这里分析每一行的log输出的含义:

  • 第1行gc日志的的分析:
  1. “GC (Allocation Failure)”代表发生了Minor GC,小括号中是发生GC的原因,这里的原因(Allocation Failure)是最常见的原因
  2. “PSYoungGen”中的PS代表的是Parallel Scavenge垃圾收集器,YoungGen代表的是年轻代
  3. “6779K->936K(9216K)”中箭头左边表示垃圾回收之前存活对象占用新生代的空间大小(6779K),箭头右边表示当执行完垃圾回收之后存活空间的占用新生代的大小(936K),小括号中的大小表示新生代总的大小(9216K),这里的新生代总空间大小为9216K即9M,但是程序中配置的jvm参数(-Xmn10M)的新生代的大小是10M,由于新生代中分了Eden和2个Survivor区,配置的比例是8:1,但是2个survivor区只有一个在使用,所以输出的大小是Eden区+1个survivor区=9M
  4. “6779K->5040K(19456K)”中箭头左边表示GC之前堆大小(6779K),箭头右边表示的是GC之后堆大小(5040K),小括号中的大小是堆总可用容量(19456K)即19M,加上浪费的1M的survivor区正好20M
  5. “0.0029926 secs”表示的是GC执行的时间,单位秒
  6. “[Times: user=0.00 sys=0.00, real=0.00 secs]”分别指的是用户空间、内核空间、真正执行的花费时间,单位秒
  • 第2行下面描述了堆区的使用情况
  1. PSYoungGen,堆区年轻代使用情况,PS指的是Parallel Scavenge垃圾收集器
  2. ParOldGen,堆区老年代使用情况,ParOld指的是Parallel Old垃圾收集器
    可以看到老年区使用情况的已使用空间的大小是4104K
 ParOldGen       total 10240K, used 4104K

这个4104K是怎么计算出来的?
执行完GC后年轻代释放的空间 = (6779K - 936K = 5843K),这个释放大小包括:释放的垃圾、被挪到老年代的空间
执行完GC后堆释放的空间 = (6779K - 5040K = 1739K),这个大小是真正释放的垃圾对象的大小
可以看出,这二者释放空间的差值正好是老年代使用的空间(5843K - 1739K = 4104K)

  • Metaspace表示的是元空间(JDK8之后的内存空间)的使用情况,垃圾收集器在这个空间的收集性价比很低。
### JVM GC Log 分析与性能调优方法 #### 1. **GC 调优的目标** GC 调优的主要目标是避免因垃圾回收而导致的程序性能下降。核心指标包括以下几个方面[^2]: - 吞吐量:执行用户代码的时间 / (执行用户代码时间 + GC 时间)。 - 延迟:GC 的暂停时间和业务逻辑执行时间内的延迟。 - 内存使用量:合理分配堆内存大小,防止频繁触发 Full GC。 #### 2. **发现和诊断问题的方法** ##### 使用工具监控 GC 行为 以下是常用的工具用于发现问题并分析其原因: - **jstat**: JDK 自带命令行工具,可提供详细的垃圾回收信息。 示例命令如下: ```bash jstat -gc <PID> 1000 5 ``` 参数说明:<PID> 是 Java 应用的进程 ID,`1000` 是每次统计之间的间隔(单位毫秒),`5` 是总统计次数。 - **VisualVM 和 Visual GC 插件**: 提供图形化界面,实时展示堆内存结构、变化趋势以及 GC 执行时间的趋势图。适用于开发环境中调试,但在生产环境下可能会影响性能。 - **Prometheus + Grafana**: 高度定制化的监控解决方案,适合复杂的生产环境。需要运维团队支持配置和维护。 ##### 分析 GC 日志 GC 日志记录了每一次垃圾回收的行为细节,可以通过以下方式获取日志数据: 开启 GC 日志的方式是在启动 Java 程序时加入参数: ```bash -javaagent:<path-to-agent>.jar \ -Xlog:gc*:file=gc.log:time,uptime,pid,tid,level,tags:filecount=5,filesize=1M ``` 上述命令会生成名为 `gc.log` 的文件,并按每 1MB 切分最多保留 5 份日志文件[^4]。 #### 3. **GC 日志分析工具** 当 GC 日志数量庞大时,手动分析变得困难,因此可以借助专门的日志分析工具完成自动化处理: - **GCViewer**: 将原始 GC 日志转换为易于理解的可视化图表。运行示例如下: ```bash java -jar gcviewer_1.3.4.jar gc_log_file.log ``` - **gceasy.io**: 在线平台,只需上传本地 GC 文件即可获得直观的报告。它不仅提供了历史对比功能,还能够给出具体的优化建议。 #### 4. **基于 GC 日志的性能调优策略** 根据 GC 日志中的关键字段进行针对性调整: - 如果 Eden 区域经常被填满,则考虑增加年轻代 (`Young Generation`) 大小或者修改 `-Xmn` 参数。 - 若老年代 (`Old Generation`) 出现过多的对象堆积现象,需评估是否应该增大整个堆空间(`Heap Size`) 或者启用 G1 收集器以改善混合回收效率[^1]。 另外需要注意的是,在实际操作过程中应当遵循一定的原则[^3]: - 上线前尽可能预先设定好最合适的 JVM 参数组合; - 对于大部分应用场景来说,默认配置已经足够满足需求,无需额外干预; - 当遇到严重的 GC 性能瓶颈时,优先排查是否存在低效编码习惯造成的资源浪费问题,比如过度创建短生命周期对象等行为。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值