摘要GC 日志是 JVM 调优的第一手资料——但面对-XX:PrintGCDetails -XX:PrintGCDateStamps -Xloggc:/path/to/gc.log这些参数你真的知道日志里的每一行代表什么吗本文从实战角度详解JDK 8 旧版日志格式与JDK 9 统一日志格式的完整解读包括 Minor GC、Full GC、晋升、对象分配失败等关键日志的含义推荐GCViewer和GCEasy两个可视化分析工具手把手教你用grep/awk/sed命令行提取关键指标最后给出一个自动化的 GC 日志分析脚本帮你从海量日志中快速定位 GC 问题。引言线上 Full GC 了怎么办这是每个 Java 工程师都可能面对的问题。回答这个问题最重要的资料就是 GC 日志——它记录了 GC 的每一次呼吸。但大多数工程师看到 GC 日志是这样的2026-04-10T15:23:45.1230800: 12345.678: [Full GC (Allocation Failure) [PSYoungGen: 1024K-0K(3584K)] [ParOldGen: 6992K-6845K(7168K)] [PSPermGen: 4321K-4321K(8192K)], 0.0123456 secs] [Times: user0.04 sys0.01, real0.01 secs]脑子里只有三个字看不懂。本文帮你把这本天书翻译成可操作的信息。一、GC 日志参数配置1.1 JDK 8 旧版日志参数# 基础参数-XX:PrintGCDetails# 打印详细 GC 信息必开-XX:PrintGCDateStamps# 打印日期时间戳JDK 8u40-XX:PrintGCTimeStamps# 打印相对时间戳JVM 启动后的秒数-XX:PrintTenuringDistribution# 打印晋升年龄分布-XX:PrintReferenceGC# 打印 SoftReference/WeakReference 等回收情况# 输出配置-Xloggc:/var/log/gc.log# 输出到文件-XX:UseGCLogFileRotation# 开启日志轮转-XX:NumberOfGCLogFiles5# 保留 5 个文件-XX:GCLogFileSize100M# 每个文件最大 100MB# 组合示例JAVA_OPTS -XX:PrintGCDetails -XX:PrintGCDateStamps -XX:PrintTenuringDistribution -XX:PrintReferenceGC -Xloggc:/var/log/gc.log -XX:UseGCLogFileRotation -XX:NumberOfGCLogFiles10 -XX:GCLogFileSize50M 1.2 JDK 9 统一日志Unified LoggingJDK 9 引入了统一日志系统Unified GC Logging所有日志包括 GC、JIT、类加载、编译器都通过-Xlog统一输出# 基础语法-Xlog[:[selector][:[output][:[level][:[decorators...]]]]]# 快速上手-Xlog:gc*info:filegc.log# gc* 所有 gc 相关标签# 常用配置-Xlog:gc*info:filegc.log:time,uptime,level,tags:filecount10,filesize100m# 参数详解# selector: 标签选择器如 gc*, gc, gcergo*, classunload# output: filepath 或 stdout/stderr# level: off/error/warning/info/debug/trace# decorators: time, uptime, timemillis, level, tags, pid, tid, worker# filecount: 保留文件数量# filesize: 单文件大小支持 K/M/G 后缀1.3 统一日志常用标签# GC 日志-Xlog:gc*info:filegc.log# 所有 GC 日志-Xlog:gc:filegc.log# 仅 GC 摘要-Xlog:gcergo*debug:filegc_ergo.log# GC 策略日志-Xlog:gcrefdebug:filegc_ref.log# 引用处理日志# JIT 编译日志-Xlog:jit*info:filejit.log# JIT 编译日志-Xlog:compilationinfo:filecomp.log# 编译事件# 类加载日志-Xlog:classloadinfo:fileclass.log# 类加载-Xlog:classunloadinfo:fileclass_unload.log# 类卸载# 完整配置示例JDK 9-Xlog:gc*info:file/var/log/gc.log:time,uptime,level,tags:filecount10,filesize100m,biases -Xlog:jit*warning:file/var/log/jit.log -Xlog:classloadinfo:file/var/log/class.log二、JDK 8 GC 日志详解2.1 Minor GC 日志格式2026-04-10T10:23:45.1230800: 1234.567: [GC Before GC: PSYoungGen: 8585216K(9437184K)] 8585216K(9437184K) - 1048576K(9437184K) [Times: user0.12 sys0.03, real0.08 secs]逐行解读┌──────────────────────────────────────────────────────────────────┐ │ 2026-04-10T10:23:45.1230800 │ │ 时间戳JDK 8u40 支持之前是相对时间1234.567 秒 │ ├──────────────────────────────────────────────────────────────────┤ │ 1234.567: 相对时间JVM 启动后的秒数 │ ├──────────────────────────────────────────────────────────────────┤ │ [GC 或 [Full GC │ │ GC Minor GC年轻代 GC │ │ Full GC 完全 GC可能是老年代 GC 或 Full GC │ ├──────────────────────────────────────────────────────────────────┤ │ PSYoungGen: 8585216K(9437184K) → 1048576K(9437184K) │ │ 含义年轻代 GC 前使用 8585MB/9437MB │ │ GC 后降为 1048MB/9437MB │ │ 内存释放8585 - 1048 7537MB~90% 回收 │ ├──────────────────────────────────────────────────────────────────┤ │ [Times: user0.12 sys0.03, real0.08 secs] │ │ user0.12s → CPU 在用户态花费的时间 │ │ sys0.03s → CPU 在内核态花费的时间系统调用 │ │ real0.08s → 实际经过的墙钟时间 │ │ 多线程效果user real并行执行时间叠加 │ └──────────────────────────────────────────────────────────────────┘2.2 Full GC 日志格式2026-04-10T10:25:00.0000800: 1309.444: [Full GC (Allocation Failure) [PSYoungGen: 1024K-0K(3584K)] [ParOldGen: 6992K-6845K(7168K)] [PSPermGen: 4321K-4321K(8192K)], 0.0123456 secs] [Times: user0.04 sys0.01, real0.01 secs]关键信息解读┌──────────────────────────────────────────────────────────────────┐ │ Full GC (Allocation Failure) │ │ 触发原因Allocation Failure分配失败老年代空间不足 │ │ 其他触发原因 │ │ - ErgonomicsJVM 自适应调整 │ │ - System.gc() 调用 │ │ - Metaspace OOM │ │ - JVMTI ForceGarbageCollection │ ├──────────────────────────────────────────────────────────────────┤ │ [PSYoungGen: 1024K-0K(3584K)] │ │ 年轻代从 1MB 降到 0完全清空 │ │ 说明这次 Full GC 顺便清理了年轻代 │ ├──────────────────────────────────────────────────────────────────┤ │ [ParOldGen: 6992K-6845K(7168K)] │ │ 老年代从 6992K 降到 6845K只回收了 147KB │ │ ⚠️ 危险信号老年代回收率极低说明大量对象无法回收 │ ├──────────────────────────────────────────────────────────────────┤ │ 0.0123456 secs │ │ Full GC 停顿 12msJDK 8 Parallel GC 正常应该在几十毫秒内 │ └──────────────────────────────────────────────────────────────────┘2.3 晋升日志Tenuring Distribution2026-04-10T10:30:00.000: [GC Desired survivor size 524288000 bytes, new threshold 7 (max 15) - age 1: 134528000 bytes, 524288000 bytes - age 2: 8388608 bytes, 524288000 bytes - age 3: 1048576 bytes, 524288000 bytes ... - age 15: 102400 bytes, 524288000 bytes ]含义分析┌──────────────────────────────────────────────────────────────────┐ │ Desired survivor size 524288000 bytes (500MB) │ │ Survivor 区目标大小能容纳 500MB 存活对象 │ ├──────────────────────────────────────────────────────────────────┤ │ new threshold 7 (max 15) │ │ 当前晋升阈值7下次 Minor GC 后超过阈值的对象晋升老年代 │ ├──────────────────────────────────────────────────────────────────┤ │ 年龄分布分析 │ │ age 1: 134MB ← 大量对象活过 1 次 Minor GC │ │ age 2: 8MB ← 大部分 age 1 对象死亡 │ │ age 3: 1MB ← 基本没有对象活这么久 │ │ │ │ 问题诊断大量对象在 age 1 时死亡但还没被回收 │ │ 原因Survivor 太小age 1 对象占满了 Survivor 空间 │ │ 建议增大 Survivor Ratio 或调整晋升阈值 │ └──────────────────────────────────────────────────────────────────┘三、可视化分析工具3.1 GCEasy最推荐GCEasy 是基于 Web 的 GC 日志分析工具支持上传日志自动分析访问https://gceasy.io 支持格式 - JDK 8 HotSpot GC 日志 - JDK 9 Unified Logging - OpenJ9 GC 日志 - 几乎所有 GC 算法格式核心指标解读指标含义正常范围Throughput应用实际运行时间占比 95% 优秀 80% 需优化GC Total Time整个观测周期 GC 总耗时越小越好GC Total CountGC 总次数结合吞吐量和停顿时间评估Avg GC Pause平均 GC 停顿时间 200ms 良好Max GC Pause最大单次 GC 停顿 1s 良好Allocation Rate对象分配速率应用相关通常 500MB/s3.2 GCViewer开源本地工具GCViewer 是开源的 GC 日志可视化工具适合内网环境使用# 下载wgethttps://github.com/chewiebug/GCViewer/releases/download/v1.34.1/gcviewer-1.34.1.jar# 运行java-jargcviewer-1.34.1.jar# 命令行分析无 GUIjava-jargcviewer-1.34.1.jar gc.log-tsummary.csvGCViewer 核心图表┌─────────────────────────────────────────────────────────────────┐ │ GCViewer 图表解读 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 堆使用图Heap Usage │ │ ┌───────────────────────────────────────────────────────────┐ │ │ │ ___ │ │ │ │ ___--- ← 老年代使用线锯齿上升 │ │ │ │ __-- │ │ │ │ __-- ← Minor GC 锯齿 │ │ │ │ __-- │ │ │ │ __-- ← 初始分配 │ │ │ │ __ │ │ │ └───────────────────────────────────────────────────────────┘ │ │ ↑ │ │ 堆增长阶段 → 周期性 Full GC → 堆收缩如果配置了 │ │ │ │ 关键洞察 │ │ - 锯齿峰值越来越高 → 老年代持续增长可能是内存泄漏 │ │ - 锯齿高度稳定 → GC 配置合理 │ │ - 锯齿间间隔越来越短 → 对象分配速率 GC 回收速率 │ │ │ └─────────────────────────────────────────────────────────────────┘四、命令行快速分析4.1 常用分析命令# 统计 GC 次数grep-cFull GCgc.log# Full GC 次数grep-cGC gc.log# 总 GC 次数# 提取 GC 停顿时间grep-oPreal\d\.\dgc.log|seds/real//|sort-n|tail-10# 统计 GC 总耗时秒awk/\[Times:/{sum$NF} END{print sum}gc.log# 查找最长 GC 停顿awk/\[Times: real/{if($NFmax)max$NF; line$0} END{print line}gc.log# 分析晋升情况grepagegc.log|head-5# 提取老年代变化grepParOldGengc.log|awk{print $5}|sort-u4.2 一键分析脚本#!/bin/bash# gc_analysis.sh - GC 日志快速分析脚本LOG_FILE$1if[-z$LOG_FILE];thenechoUsage:$0gc_log_fileexit1fiechoecho GC 日志分析报告:$LOG_FILEechoechoecho【1. GC 次数统计】minor_gc$(grep-c^\[GC $LOG_FILE2/dev/null||echo0)full_gc$(grep-c^\[Full GC$LOG_FILE2/dev/null||echo0)echoMinor GC 次数:$minor_gcechoFull GC 次数:$full_gcechoecho【2. GC 停顿时间统计】awk/\[Times: real/ { gsub(/real/, , $NF) gsub(/secs.*/, , $NF) times[NR] $NF sum $NF if ($NF max) max $NF count } END { if (count 0) { avg sum / count printf 总 GC 次数: %d\n, count printf 总 GC 耗时: %.3f 秒\n, sum printf 平均停顿: %.3f 秒\n, avg printf 最大停顿: %.3f 秒\n, max } }$LOG_FILEechoecho【3. 最近 5 次 Full GC】grepFull GC$LOG_FILE|tail-5echoecho【4. 对象晋升年龄分布】grep-A10Desired survivor$LOG_FILE|tail-15echoecho五、GC 日志速查问题诊断日志特征可能问题建议操作Full GC 后老年代没降多少内存泄漏/大对象持有Dump 分析Minor GC 后大量对象晋升Survivor 太小调 SurvivorRatioGC 停顿时间越来越长老年代碎片化增加堆或切换 G1Allocation Failure 频繁分配速率过高优化代码或增大年轻代GC 只在特定时间发生定时任务/缓存失效优化定时逻辑Metaspace 持续增长类加载器泄漏检查动态类加载总结GC 日志是 JVM 调优的第一手资料。JDK 8 用-XX:PrintGCDetailsJDK 9 用-Xlog:gc*info。分析 GC 日志的核心是找到 GC 次数和停顿时间与业务负载的对应关系识别异常模式老年代不降、晋升过多、停顿递增然后针对性调整参数。系列导航上一篇【JVM深度解析】第10篇内存配置与调优实战下一篇【JVM深度解析】第12篇JVM性能监控工具实战系列目录JVM深度解析系列全集JVM系列快速索引篇号标题状态01-10基础原理/GC深度/参数配置✅11GC日志配置与可视化分析✅12JVM性能监控工具实战⏳13生产环境JVM配置最佳实践⏳14-32调优案例/高级特性/并发⏳参考资料GCEasy - GC Log AnalysisGCViewer - Open Source GC AnalyzerOracle JDK 9 GC Logging GuideAnalyzing GC Logs - Netflix Tech BlogUnderstanding GC Logs