JVM中性能调优工具功能详解(上)
本文章内容基于jdk1.8进行讲解
一、jps
jps(JavaVirtual Machine Process Status Tool)它将打印所有正在运行的 Java 进程的相关信息。在默认情况下,jps的输出信息包括 Java 进程的进程 ID 以及主类名。我们还可以通过追加参数,来打印额外的信息。
jps
jps -q 打印启动java程序的进程号
jps –l:输出主类或者jar的完全路径名
jps –v :输出jvm参数
jps –m :输出main method的参数
结合使用 jps -mlv
二、jstat
jstat(Java Virtual Machine statistics monitoring tool)允许用户查看目标 Java 进程的类加载、即时编译以及垃圾回收相关的信息。它常用于检测垃圾回收问题以及内存泄漏问题。
我们可以通过jstat -options命令来查看可以检测的区域
class | 类加载器的统计信息 |
---|---|
compiler | JIT(即时编译器) 的统计信息 |
gc | GC管理堆的统计信息 |
gccapacity | 堆内存容量统计 |
gccause | 垃圾收集统计信息的摘要(与-gcutil相同),包括上一次和当前(如果适用)垃圾收集事件的原因 |
gcmetacapacity | 元空间信息统计 |
gcnew | 新生代信息统计 |
gcnewcapacity | 新生代信息统计及内存使用情况 |
gcold | 统计老年代和元空间使用情况 |
gcoldcapacity | 统计老年代内存使用情况 |
gcutil | 垃圾回收统计 |
printcompilation | Hotspot方法编译统计情况 |
jstat 命令格式
jstat [-options] [pid] [间隔时间/默认单位是毫秒] [查询次数]
jstat -class --类加载器的统计信息
Loaded | 加载class的数量 |
---|---|
Bytes | 所占空间的大小(KB) |
Unloaded | 未加载数量 |
Bytes | 未加载占用空间(KB) |
Time | 执行类加载和卸载操作所花费的时间 |
jstat -compiler --JIT(即时编译器) 的统计信息
Compiled | 执行的编译任务数 |
---|---|
Failed | 失败编译的任务数 |
Invalid | 无效的编译任务数 |
Time | 执行编译任务所花时间 |
FailedType | 上次失败编译的编译类型 |
FailedMethod | 上次编译失败的类名和方法 |
jstat -gc --GC管理堆的统计信息
S0C | 当前第一个幸存区空间容量的大小(KB) |
---|---|
S1C | 当前第二个幸存区空间容量的大小(KB) |
S0U | 第一个幸存区空间的使用大小(KB) |
S1U | 第二个幸存区空间的使用大小(KB) |
EC | 当前eden区空间容量(KB) |
EU | 当前eden空间使用大小(KB) |
0C | 当前老年代空间容量(KB) |
0U | 老年代空间使用大小(KB) |
MC | 元空间容量(KB) |
MU | 元空间使用大小(KB) |
CCSC | 压缩类空间大小(KB) |
CCSU | 已使用的压缩类空间(kB) |
YGC | 年轻代垃圾回收次数 |
YGCT | 年轻代垃圾回收消耗时间 |
FGC | 老年代垃圾回收次数 |
FGCT | 老年代垃圾回收消耗时间 |
GCT | 垃圾回收消耗总时间 |
[压缩类空间指的是被压缩指针所指向的空间,默认大小1G,可以通过CompressedClassSpaceSize调整]
jstat -gccapacity --堆内存容量统计
NGCMN | 新生代最小容量(KB) |
---|---|
NGCMX | 新生代最大容量(KB) |
NGC | 当前新生代容量(KB) |
S0C | 当前第一个幸存区空间容量的大小(KB) |
S1C | 当前第二个幸存区空间容量的大小(KB) |
EC | 当前eden区空间容量(KB) |
OGCMN | 老年代最小容量(KB) |
OGCMX | 老年代最大容量(KB) |
OGC | 当前老年代容量(KB) |
OC | 当前老年代容量(KB) |
MCMN | 最小元数据容量(KB) |
MCMX | 最大元数据容量(KB) |
MC | 当前元数据空间大小(KB) |
CCSMN | 最小压缩类空间大小(KB) |
CCSMX | 最大压缩类空间大小(KB) |
CCSC | 当前压缩类空间大小(KB) |
YGC | 年轻代gc次数 |
FGC | 老年代gc次数 |
jstat -gccause --垃圾收集统计信息的摘要(与-gcutil相同),包括上一次和当前(如果适用)垃圾收集事件的原因。
S0 | 第一个辛存区的使用空间占当前容量的百分比 |
---|---|
S1 | 第二个辛存区的使用空间占当前容量的百分比 |
E | 伊甸区已用空间占当前容量的百分比 |
O | 老年代已用空间占当前容量的百分比 |
M | 元空间已用空间占当前容量的百分比 |
CCS | 以百分比表示的压缩类空间利用率 |
YGC | 年轻代垃圾回收次数 |
YGCT | 年轻代垃圾回收消耗时间 |
FGC | 老年代垃圾回收次数 |
FGCT | 老年代垃圾回收消耗时间 |
GCT | 垃圾回收消耗总时间 |
LGCC | 上次垃圾回收的原因 |
GCC | 当前垃圾回收的原因 |
jstat -gcmetacapacity --元空间信息统计
MCMN | 最小元空间容量(KB) |
---|---|
MCMX | 最大元空间容量(KB) |
MC | 元空间容量(KB) |
CCSMN | 压缩类空间最小容量(KB) |
CCSMX | 压缩类空间最大容量(KB) |
CCSC | 当前压缩类空间大小(KB) |
YGC | 年轻代垃圾回收次数 |
FGC | 老年代垃圾回收次数 |
FGCT | 老年代垃圾回收消耗时间 |
GCT | 垃圾回收消耗总时间 |
jstat -gcnew --新生代信息统计
S0C | 第一个幸存区大小(KB) |
---|---|
S1C | 第二个幸存区的大小(kB) |
S0U | 第一个幸存区空间的使用大小(KB) |
S1U | 第二个幸存区空间的使用大小(KB) |
TT | 对象在新生代存活的次数 |
MTT | 对象在新生代存活的最大次数 |
DSS | 期望的幸存区大小(KB) |
EC | 当前伊甸区空间容量(KB) |
EU | 伊甸空间利用率(KB) |
YGC | 年轻代GC次数 |
YGCT | 年轻代垃圾回收消耗时间 |
jstat -gcnewcapacity --新生代信息统计及内存使用情况
NGCMN | 新生代最小容量(KB) |
---|---|
NGCMX | 新生代最大容量(KB) |
NGC | 当前新生代容量(KB) |
S0CMX | 第一个幸存区最大大小(KB) |
S0C | 当前第一个幸存区大小(KB) |
S1CMX | 第二个幸存区最大大小(KB) |
S1C | 当前第二个幸存区大小(KB) |
ECMX | 最大伊甸区大小(KB) |
EC | 当前伊甸园区大小(KB) |
YGC | 年轻代垃圾回收次数 |
FGC | 老年代回收次数 |
jstat -gcold --统计老年代和元空间使用情况
MC | 元空间容量(KB) |
---|---|
MU | 元空间使用大小(KB) |
CCSC | 压缩类空间大小(KB) |
CCSU | 压缩类空间使用大小(KB) |
OC | 老年代大小(KB) |
OU | 老年代使用大小(KB) |
YGC | 年轻代垃圾回收次数 |
FGC | 老年代垃圾回收次数 |
FGCT | 老年代垃圾回收消耗时间 |
GCT | 垃圾回收消耗总时间 |
jstat -gcoldcapacity --统计老年代内存使用情况
OGCMN | 老年代最小容量 (KB) |
---|---|
OGCMX | 老年代最大容量(KB) |
OGC | 当前老年代大小(KB) |
OC | 老年代大小(KB) |
YGC | 年轻代垃圾回收次数 |
FGC | 老年代垃圾回收次数 |
FGCT | 老年代垃圾回收消耗时间 |
GCT | 垃圾回收消耗总时间 |
jstat -printcompilation --Hotspot方法编译统计情况
Compiled | 最近编译方法的数量 |
---|---|
Size | 最近编译方法的字节码数量 |
Type | 最近编译方法的编译类型 |
Method | 类名和方法名,用于标识最近编译的方法。类名使用斜杠(/)而不是点(.)作为名称空间分隔符。方法名是指定类中的方法。这两个字段的格式与HotSpot-XX:+printcomilation选项一致。 |
当使用 G1 GC 时,Java 虚拟机不再设置 Eden 区、Survivor 区,老年代区的内存边界,而是将堆划分为若干个等长内存区域。每个内存区域都可以作为 Eden 区、Survivor 区以及老年代区中的任一种,并且可以在不同区域类型之间来回切换。
换句话说,逻辑上我们只有一个 Survivor 区。当需要迁移 Survivor 区中的数据时(即 Copying GC),我们只需另外申请一个或多个内存区域,作为新的 Survivor 区。因此,Java 虚拟机决定在使用 G1 GC 时,将所有 Survivor 内存区域的总容量以及已使用量存放至 S1C 和 S1U 中,而 S0C 和 S0U 则被设置为 0。当发生垃圾回收时,Java 虚拟机可能出现 Survivor 内存区域内的对象全被回收或晋升的现象。在这种情况下,Java 虚拟机会将这块内存区域回收,并标记为可分配的状态。这样子做的结果是,堆中可能完全没有 Survivor 内存区域,因而相应的 S1C 和 S1U 将会是 0。
jstat还可以用来判断是否出现内存泄漏。在长时间运行的 Java 程序中,我们可以运行jstat命令连续获取多行性能数据,并取这几行数据中 OU 列(即已占用的老年代内存)的最小值。然后,我们每隔一段较长的时间重复一次上述操作,来获得多组 OU 最小值。如果这些值呈上涨趋势,则说明该 Java 程序的老年代内存已使用量在不断上涨,这意味着无法回收的对象在不断增加,因此很有可能存在内存泄漏。