JStat 是一款 JDK 中的简单实用工具,用于提供与 JVM 性能相关的统计信息,如:垃圾回收、编译活动等等。JStat 的主要优势在于其能够在 JVM 运行时动态捕获这些指标,无需任何先决条件。这是什么意思呢?例如,如果您想捕获与垃圾回收相关的统计信息,那就需要在启动 JVM 之前传递下面的参数:
-Xlog:gc*:file={file-path}
这一参数将启用 GC 日志并将其输出至特定的文件路径。如果您没有传递此参数,那么 GC 相关的统计数据就不会生成。这就是 JStat 能够助您一臂之力的时候。您可动态连接至 JVM 并捕获 GC,然后整理出如下所示的相关统计数据。
如何启动 JStat?
执行以下指令,很轻松就能启动 JStat 了。
jstat -gc -t 11656 10000 30
-gc:与垃圾回收相关的统计数据将被输出
-t:自 JVM 启动以来的时间戳将被输出
11656:目标 JVM 进程 ID
10000:统计数据将每隔 10,000 毫秒(即:10 秒)输出一次。
30:统计数据将被迭代输出 30 次。因此,上述选项将让 JVM 在 300 秒的输出指标(即:10 秒 x 30 次)。
(注意,除了 -gc 之外,您还可以传递多种选项以生成不同的数据集。如需了解有关不同选项的详细信息,可参考此处。)
由 JStat 生成的数据
当您使用上述选项启动 JStat 时将输出以下内容:

图:JStat 输出
Timestamp – 目标 JVM 启动后的运行时间(秒)。
S0C – Survivor 0 区域容量(KB)
S1C – Survivor 1 区域容量(KB)
S0U – Survivor 0 区域已使用空间(KB)
S1U – Survivor 1 区域已使用空间(KB)
EC – Eden 区域容量(KB)
EU – Eden 区域已使用空间(KB)
OC – Old 区域容量(KB)
OU – Old 区域已使用空间(KB)
MC – Metaspace 区域容量(KB)
MU – Metaspace 区域已使用空间(KB)
CCSC – 压缩类空间区域容量(KB)
CCSU – 压缩类空间区域已使用空间(KB)
YGC – 截至目前 Young GC 事件发生的次数
YGCT – 截至目前 Young GC 所花费的时间
FGC – 截至目前 Full GC 事件发生的次数
FGCT – 截至目前 Full GC 所花费的时间
GCT – 截至目前 GC 所花费的总时间(大致等于 YGCT + FGCT)
如何理解 JStat 输出?
了解这些信息后,让我们来试着解释示例中 JStat 工具所输出的第一行内容:

图:JStat 输出内容首行
时间戳 | JVM 启动后的运行时间(秒) | = 164.9 秒 |
Young 代容量 | Young 代由 Eden 区域、Survivor 0、Survivor 1 组成。因此其容量为: S0C + S1C + EC | = 116224.0 + 116224.0 + 116736.0 = 349184 KB = 341 MB |
Young 代已使用大小 | S0U + S1U + EU | = 0 + 1520 + 68761.8 = 70281.8 KB = 68.63 MB |
Old 代容量 | OC | = 431616 KB = 421.5 MB |
Old 代已使用大小 | OU | = 280502.5 KB = 273.93 MB |
Metaspace 容量 | MC | = 32384 KB = 31.62 MB |
Metaspace 已使用大小 | MU | = 31155.5 KB = 30.42 MB |
Young GC 数 | YGC | = 29 |
Young GC 花费时间 | YGCT | = 0.836 秒 |
GC 花费总时间 | GCT | = 2.27 秒 |
可用于分析 JStat 输出的工具
使用 JStat 时所需应对的挑战之一,就是您需要手工分析生成的统计数据。这项工作十分烦人,因为您可能需要花费相当长的时间才能理解其中的一行内容。对此,您可以使用 GCeasy 工具来解析 JStat 输出并生成信息量巨大的图表与指标。可以看看这份使用 GCeasy 分析上述 JStat 输出时生成的 JStat 分析报告。
JStat 的局限
JStat 也存在一定的局限性:
(a). JStat 无法提供有关 GC 活动的详细信息。其只能提供刚刚好够的信息量。比如下面的一些例子,就是您无法通过 JStat 所获知的东西:
- 如果多个 GC 事件在一次性取样中报告,那么我们将无法获知其中每次 GC 事件的时间。
- sys(即:kernel)、user(即:Java 层)中所花费的时间
- 有多少 GC 线程正在工作以及其所花费的时间。
- 一个 GC 事件中有多个子阶段(如:initial mark、clean-up、remark、concurrent mark…)。我们将无法获得与之相关的分解信息。
- 每次 GC 活动所回收的字节数
(b).有时,JStat 所提供的数据也可能会具有误导性。
如果您想进行准确的 GC 分析,那么 GC 日志可能是更加可靠的方式。
Leave a Reply