Jstat 和 Jvisualvm 显示不同的堆数 usage/allocation

Jstat and Jvisualvm show different numbers for heap usage/allocation

有一台服务器,我无法在其上 运行 任何 GUI-based 分析器(例如 jvisualvm)来监视 运行ning Java 进程的堆。根据this answer,我可以使用jstat -gc <pid>并查看OU和OC列以找出堆使用和分配。

但我只是比较了另一台服务器上的 jvisualvm 和 jstat,它们显示的堆使用和分配数字并不相同。

Jvisualvm 显示 Java 进程为堆分配了大约 1GB,并使用了大约 500MB:

但是对于同一个进程,jstat 仅在 OC 列下显示大约 700MB,在 OU 列下显示大约 226MB:

# jstat -gc 39621
S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT
16384.0 17920.0 3984.0  0.0   322560.0 10320.4   699392.0   226295.2  83968.0 47921.1  11966   66.103  12      3.083   69.186

为什么 jvisualvm 和 jstat 显示不同的堆使用和分配数字?

原来jstat的EU和OU列加起来大约等于jvisualvm中显示的heap使用量。对于我正在监视的进程,EU+OU 总是比 jvisualvm 中显示的少大约 12 MB。 (在我在问题中提供的示例中,jvisualvm 显示 506 MB 的堆使用情况,而 jstat 显示 EU+OU = 240 MB。因此,在堆使用率下降到 250 MB 之后,我必须立即使用 运行 jstat。 )

jstat 的EC 和OC 列相加大约等于jvisualvm 中显示的堆分配。对于我正在监视的进程,EC+OC 比 jvisualvm 中显示的少大约 45-60 MB。

对于 Java 8,jstat 实用程序已更新,对于

jstat –gc <PID>

输出中有这些字段:

S0C     S1C      S0U   S1U     EC       EU        OC         OU        MC      MU      CCSC   CCSU    YGC     YGCT    FGC     FGCT     GCT   

39936.0 29184.0  0.0   29035.4 273920.0 170661.5  699392.0   39235.9   98480.0 97022.7 8624.0 8163.3     63    0.925  38      2.363    3.289

堆使用

要获取当前堆使用情况,大约是jVisualJM中的值,需要加上以下值:

S0U: Survivor space 0 utilization (kB)

S1U: Survivor space 1 utilization (kB)

EU: Eden space utilization (kB)

OU: Old space utilization (kB)

正在查看 Java 8 Virtual Machine Garbage Collection Tuning Guide, 堆似乎由 'Young' 代(Eden & Survivor 0 & 1 spaces)和 'Old' 代(Old space)组成。

元space用法

要获取当前metaspace用法,大约是jVisualJM中的值,需要以下大小:

MU: Metaspace utilization (kB)

备注

无论出于何种原因,我从未能够在 jstat 和 jVisualJM 之间获得完全相同的值,但足够接近以允许自信地使用这两种工具。

JVM 内存池

有关 JVM 内存池的更多详细信息,请参阅此 Whosebug question & answer,其中涵盖 Java 7 和 8。

Java 8 Using JConsole guide中也有一些信息,但令人惊讶的是,这仍然提到了 Java 7 Permanent Generation space 而不是 Java 8 Metaspace.

简单的 unix 命令通过 jstat 查看当前保留的堆大小:(它匹配 jconsole 数字)

jstat -gc <pid> 3000 | awk '{split([=10=],a," "); print a[3]+a[4]+a[6]+a[8]}'