一、jstat概述
Jstat 是JDK自带的一个轻量级小工具。全称“Java Virtual Machine statistics monitoring tool”,它位于java的bin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。可见,Jstat是轻量级的、专门针对JVM的工具,非常适用。由于JVM内存设置较大,图中百分比变化不太明显
一个极强的监视VM内存工具。可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量。
jstat工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。
执行:cd $JAVA_HOME/bin中执行jstat,注意jstat后一定要跟参数。
1.1、语法结构:
Usage: jstat -help|-options
jstat -
jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数]
参数解释:
Options — 选项,我们一般使用 -gcutil 查看gc情况
vmid — VM的进程号,即当前运行的java进程号
interval– 间隔时间,单位为秒或者毫秒
count — 打印次数,如果缺省则打印无数次
示例:jstat -gcutil 15670 1000 10
1.2、具体使用
其中Pid获取
window下:jps
linux:jps或ps -ef | grep java
1》垃圾回收统计: jstat -gc pid
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
2》堆内存统计:jstat -gccapacity pid
可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小,
如:PGCMN显示的是最小perm的内存使用量,PGCMX显示的是perm的内存最大使用量,
PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。
其他的可以根据这个类推, OC是old内纯的占用量。
NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC:当前新生代容量
S0C:第一个幸存区大小
S1C:第二个幸存区的大小
EC:伊甸园区的大小
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC:当前老年代大小
OC:当前老年代大小
MCMN:最小元数据容量
MCMX:最大元数据容量
MC:当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC:当前压缩类空间大小
YGC:年轻代gc次数
FGC:老年代GC次数
3》统计gc信息统计:jstat -gcutil pid
S0:幸存1区当前使用比例
S1:幸存2区当前使用比例
E:伊甸园区使用比例
O:老年代使用比例
M:元数据区使用比例
CCS:压缩使用比例
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
示例:jstat -gcutil 15670 1000 10
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 10.00 0.00 17.63 19.90 0 0.000 0 0.000 0.000
4》新生代垃圾回收统计:jstat -gcnew pid
S0C:第一个幸存区大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
TT:对象在新生代存活的次数
MTT:对象在新生代存活的最大次数
DSS:期望的幸存区大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
5》新生代内存统计:jstat -gcnewcapacity pid
NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC:当前新生代容量
S0CMX:最大幸存1区大小
S0C:当前幸存1区大小
S1CMX:最大幸存2区大小
S1C:当前幸存2区大小
ECMX:最大伊甸园区大小
EC:当前伊甸园区大小
YGC:年轻代垃圾回收次数
FGC:老年代回收次数
6》老年代垃圾回收统计:jstat -gcold pid
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
OC:老年代大小
OU:老年代使用大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
7》老年代内存统计:jstat -gcoldcapacity pid
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC:当前老年代大小
OC:老年代大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
8》持久代:jstat -gcpermcapacity pid
perm对象的信息及其占用量。
9》类加载统计:jstat -class pid
Loaded:加载class的数量
Bytes:所占用空间大小
Unloaded:未加载数量
Bytes:未加载占用空间
Time:时间
10》编译统计:jstat -compiler pid
Compiled:编译数量。
Failed:失败数量
Invalid:不可用数量
Time:时间
FailedType:失败类型
FailedMethod:失败的方法
11》JVM编译方法统计:jstat -printcompilation pid
Compiled:最近编译方法的数量
Size:最近编译方法的字节码数量
Type:最近编译方法的编译类型。
Method:方法名标识。
12、jstat -gcmetacapacity pid元数据空间统计
MCMN:最小元数据容量
MCMX:最大元数据容量
MC:当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC:当前压缩类空间大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
1.3、术语的中文解释:
S0C:年轻代中第一个survivor(幸存区)的容量 (字节)
S1C:年轻代中第二个survivor(幸存区)的容量 (字节)
S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
EC:年轻代中Eden(伊甸园)的容量 (字节)
EU:年轻代中Eden(伊甸园)目前已使用空间 (字节)
OC:Old代的容量 (字节)
OU:Old代目前已使用空间 (字节)
PC:Perm(持久代)的容量 (字节)
PU:Perm(持久代)目前已使用空间 (字节)
YGC:从应用程序启动到采样时年轻代中gc次数
YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)
FGC:从应用程序启动到采样时old代(全gc)gc次数
FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT:从应用程序启动到采样时gc用的总时间(s)
NGCMN:年轻代(young)中初始化(最小)的大小 (字节)
NGCMX:年轻代(young)的最大容量 (字节)
NGC:年轻代(young)中当前的容量 (字节)
OGCMN:old代中初始化(最小)的大小 (字节)
OGCMX:old代的最大容量 (字节)
OGC:old代当前新生成的容量 (字节)
PGCMN:perm代中初始化(最小)的大小 (字节)
PGCMX:perm代的最大容量 (字节)
PGC:perm代当前新生成的容量 (字节)
S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
E:年轻代中Eden(伊甸园)已使用的占当前容量百分比
O:old代已使用的占当前容量百分比
P:perm代已使用的占当前容量百分比
M:元数据区使用比例
S0CMX:年轻代中第一个survivor(幸存区)的最大容量 (字节)
S1CMX :年轻代中第二个survivor(幸存区)的最大容量 (字节)
ECMX:年轻代中Eden(伊甸园)的最大容量 (字节)
DSS:当前需要survivor(幸存区)的容量 (字节)(Eden区已满)
TT:持有次数限制
MTT: 最大持有次数限制
二、Jmap
1、jmap -heap pid
查看jvm参数设置以及内存使用情况
jmap -heap 29310
Attaching to process ID 29310, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.111-b14
using thread-local object allocation.
Parallel GC with 4 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 2099249152 (2002.0MB)
NewSize = 44040192 (42.0MB)
MaxNewSize = 699400192 (667.0MB)
OldSize = 88080384 (84.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 680525824 (649.0MB)
used = 472830496 (450.9263000488281MB)
free = 207695328 (198.07369995117188MB)
69.48016949904901% used
From Space:
capacity = 9437184 (9.0MB)
used = 8669680 (8.268051147460938MB)
free = 767504 (0.7319488525390625MB)
91.86723497178819% used
To Space:
capacity = 9437184 (9.0MB)
used = 0 (0.0MB)
free = 9437184 (9.0MB)
0.0% used
PS Old Generation
capacity = 612892672 (584.5MB)
used = 180096000 (171.7529296875MB)
free = 432796672 (412.7470703125MB)
29.38459019461078% used
43745 interned Strings occupying 4936472 bytes.
从结构上分为几个部分:HeapConfiguration、Heap Usage,其中Heap Useage又分为PS Young Generation和PS Old Generation,PS Young Generation又分为Eden Space\From Space\To space,所以可以看出这个命令也主要是围绕GC操纵空间堆来的,包括堆的基本配置以及堆的使用情况,这个命令其实很实用,上面就是配置下面就是实用情况,当堆内存不足的时候可以很直观的看出哪个参数设置得不合理,如果看堆设置没看出有什么问题,那么再结合jstat -gcutil pid看看垃圾回收情况,差不多就能看出大概是什么原因导致堆内存溢出了。
新生代的内存回收就是采用空间换时间的方式;
如果from区使用率一直是100% 说明程序创建大量的短生命周期的实例,使用jstat统计一下jvm在内存回收中发生的频率耗时以及是否有full gc,使用这个数据来评估一内存配置参数、gc参数是否合理;
多次ygc后如果s区没变化,这种情况不出意外就是担保了,可以jstat持续观察下;
根据打印的结果:默认存活区与eden比率=2:8
1)查看eden区:649M
2)两个存活区大小:都为9M
3)年轻代大小:300M
4)老年代大小:400M
5)持久代大小:100M
6)最大堆内存大小:年轻代大小+老年代大小=700M
7)java应用程序占用内存大小:最大堆内存大小+持久代大小=700M+100M=800M
2、jmap pid
打印出某个java进程内存内的所有对象的情况,如:产生了哪些对象以及数量
3、jmap -dump:format=b,file=heap.bin pid
format 格式,这里b是二进制的意思 ;file 保存路径及文件名;pid 进程号
这个命令会在当前路径生成一个名为heap.bin的二进制内存dump文件,这种文件有专门的分析工具如jvirsual Vm ,mat等
jmap -dump:format=b,file=outfile 3024 可以将3024进程的内存heap输出出来到outfile文件里,再配合MAT(内存分析工具(Memory Analysis Tool)或与jhat (Java Heap Analysis Tool)一起使用,能够以图像的形式直观的展示当前内存是否有问题。
从安全点日志看,从Heap Dump开始,整个JVM都是停顿的,考虑到IO(虽是写到Page Cache,但或许会遇到background flush),几G的Heap可能产生几秒的停顿,在生产环境上执行时谨慎再谨慎。
live的选项,实际上是产生一次Full GC来保证只看还存活的对象。有时候也会故意不加live选项,看历史对象。
Dump出来的文件建议用JDK自带的VisualVM或Eclipse的MAT插件打开,对象的大小有两种统计方式:
- 本身大小(Shallow Size):对象本来的大小。
- 保留大小(Retained Size): 当前对象大小 + 当前对象直接或间接引用到的对象的大小总和。
看本身大小时,占大头的都是char[] ,byte[]之类的,没什么意思(用jmap -histo:live pid 看的也是本身大小)。所以需要关心的是保留大小比较大的对象,看谁在引用这些char[], byte[]。
(MAT能看的信息更多,但VisualVM胜在JVM自带,用法如下:命令行输入jvisualvm,文件->装入->堆Dump->检查 -> 查找20保留大小最大的对象,就会触发保留大小的计算,然后就可以类视图里浏览,按保留大小排序了)
4、jmap -histo:live pid|less
堆中活动对象以及其大小
说明:instances(实例数)、bytes(大小)、classs name(类名)。它基本是按照使用使用大小逆序排列的。
num #instances #bytes class name
----------------------------------------------
1: 3640 281760 [C
2: 476 164320 [B
3: 3624 86976 java.lang.String
4: 728 82880 java.lang.Class
5: 651 39824 [Ljava.lang.Object;
6: 636 25440 java.util.LinkedHashMap$Entry
……
287: 1 16 sun.util.resources.LocaleData$LocaleDataResourceBundleControl
Total 12964 822808
从上面的信息可以看出排在前三位的分别是java.lang.String、java.lang.class以及java.util.LinkHashMap$Entry
#instance 是对象的实例个数
#bytes 是总占用的字节数
class name 对应的就是 Class 文件里的 class 的标识
B 代表 byte
C 代表 char
D 代表 double
F 代表 float
I 代表 int
J 代表 long
Z 代表 boolean
前边有 [ 代表数组, [I 就相当于 int[]
对象用 [L+ 类名表示
jmap -histo:live pid>a.log
可以观察heap中所有对象的情况(heap中所有生存的对象的情况)。包括对象数量和所占空间大小。 可以将其保存到文本中去,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。
jmap -histo:live 这个命令执行,JVM会先触发gc,然后再统计信息。
三、jinfo
可以输出并修改运行时的java进程信息,预发: jinfo --help
Usage:
jinfo [option] <pid>
(to connect to running process)
jinfo [option] <executable <core>
(to connect to a core file)
jinfo [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)
where <option> is one of:
-flag <name> to print the value of the named VM flag
-flag [+|-]<name> to enable or disable the named VM flag
-flag <name>=<value> to set the named VM flag to the given value
-flags to print VM flags
-sysprops to print Java system properties
<no option> to print both of the above
-h | -help to print this help message
查看jvm参数:jinfo -flags
查看系统参数:jinfo -sysprops
虚拟机参数:java -XX:+PrintFlagsFinal -version | grep manageable
查看是否开启 GC 日志的打印:jinfo -flag PrintGC
打开日志:jinfo -flag +PrintGC 43520 或 jinfo -flag +PrintGCDetails 43520
关闭日志:jinfo -flag -PrintGC 43520 或 jinfo -flag -PrintGCDetails 43520