概述
jmap命令有下面几种常用的用法:
•jmap [pid]
•jmap -histo:live [pid] >a.log
•jmap -dump:live,format=b,file=xxx.xxx [pid]
用得最多是后面两个。其中,jmap -histo:live [pid] 可以查看当前Java进程创建的活跃对象数目和占用内存大小。
jmap -dump:live,format=b,file=xxx.xxx [pid] 则可以将当前Java进程的内存占用情况导出来,方便用专门的内存分析工具(例如:MAT)来分析。
jmap -heap <pid>输出
[tomcat@n01 ~]$ /opt/java/jdk1.8.0_101/bin/jmap -heap 11368
Attaching to process ID 11368, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.101-b13
using thread-local object allocation.
Parallel GC with 2 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 2684354560 (2560.0MB)
NewSize = 1073741824 (1024.0MB)
MaxNewSize = 1073741824 (1024.0MB)
OldSize = 1610612736 (1536.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 = 852492288 (813.0MB)
used = 420427144 (400.95056915283203MB)
free = 432065144 (412.04943084716797MB)
49.31741317993014% used
From Space:
capacity = 113770496 (108.5MB)
used = 2299712 (2.19317626953125MB)
free = 111470784 (106.30682373046875MB)
2.021360617079493% used
To Space:
capacity = 107479040 (102.5MB)
used = 0 (0.0MB)
free = 107479040 (102.5MB)
0.0% used
PS Old Generation
capacity = 1610612736 (1536.0MB)
used = 50883368 (48.526161193847656MB)
free = 1559729368 (1487.4738388061523MB)
3.1592552860577903% used
interned Strings occupying 3138384 bytes.
MaxHeapFreeRatio: GC后如果发现空闲堆内存占到整个预估堆内存的N%(百分比),则收缩堆内存的预估最大值, 预估堆内存是堆大小动态调控的重要选项之一. 堆内存预估最大值一定小于或等于固定最大值(-Xmx指定的数值). 前者会根据使用情况动态调大或缩小, 以提高GC回收的效率
MinHeapFreeRatio: GC后如果发现空闲堆内存占到整个预估堆内存的N%(百分比), 则放大堆内存的预估最大值
MaxHeapSize: 即-Xmx, 堆内存大小的上限
InitialHeapSize: 即-Xms, 堆内存大小的初始值
NewSize: 新生代预估堆内存占用的默认值
MaxNewSize: 新生代占整个堆内存的最大值
OldSize: 老年代的默认大小, default size of the tenured generation
NewRatio: 老年代对比新生代的空间大小, 比如2代表老年代空间是新生代的两倍大小. The ratio of old generation to young generation.
SurvivorRatio: Eden/Survivor的值. 这个值的说明, 很多网上转载的都是错的. 8表示Survivor:Eden=1:8, 因为survivor区有2个, 所以Eden的占比为8/10. Ratio of eden/survivor space size. -XX:SurvivorRatio=6 sets the ratio between each survivor space and eden to be 1:6, each survivor space will be one eighth of the young generation.
xxxRatio一般以xxx作为分母,NewRatio是Old:New,SurvivorRatio是Eden:Survivor
Eden:Survivor = 8: 1
Old: New = 2:1
MetaspaceSize: 分配给类元数据空间的初始大小(Oracle逻辑存储上的初始高水位,the initial high-water-mark ). 此值为估计值. MetaspaceSize设置得过大会延长垃圾回收时间. 垃圾回收过后, 引起下一次垃圾回收的类元数据空间的大小可能会变大
MaxMetaspaceSize: 是分配给类元数据空间的最大值, 超过此值就会触发Full GC. 此值仅受限于系统内存的大小, JVM会动态地改变此值
CompressedClassSpaceSize: 类指针压缩空间大小, 默认为1G
G1HeapRegionSize: G1区块的大小, 取值为1M至32M. 其取值是要根据最小Heap大小划分出2048个区块. With G1 the Java heap is subdivided into uniformly sized regions. This sets the size of the individual sub-divisions. The default value of this parameter is determined ergonomically based upon heap size. The minimum value is 1Mb and the maximum value is 32Mb. Sets the size of a G1 region. The value will be a power of two and can range from 1MB to 32MB. The goal is to have around 2048 regions based on the minimum Java heap size.
指针压缩1. 64位平台上默认打开
1)使用-XX:+UseCompressedOops压缩对象指针
"oops"指的是普通对象指针("ordinary" object pointers)。
Java堆中对象指针会被压缩成32位。
使用堆基地址(如果堆在低26G内存中的话,基地址为0)
2)使用-XX:+UseCompressedClassPointers选项来压缩类指针
对象中指向类元数据的指针会被压缩成32位
类指针压缩空间会有一个基地址
2. 元空间和类指针压缩空间的区别
1)类指针压缩空间只包含类的元数据,比如InstanceKlass, ArrayKlass
仅当打开了UseCompressedClassPointers选项才生效
为了提高性能,Java中的虚方法表也存放到这里
这里到底存放哪些元数据的类型,目前仍在减少
2)元空间包含类的其它比较大的元数据,比如方法,字节码,常量池等。
使用 jmap -heap pid ,可以查看各个代的内存使用情况。
$ jmap -heap 2083 |
可以观察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的内存使用情况
$ jmap -dump:format=b,file=heapdump.hprof <pid> |
导出heap dump到文件heapdump.hprof
然后利用MAT工具分析是否存在内存泄漏等等
$ jmap -histo:live 2083 | head -n 100 |
可以观察heap中前100个占用内存最大的对象的情况(heap中所有生存的对象的情况)。包括对象数量和所占空间大小。
jmap -histo:live 2083 | head -n 100
[hadoop@DEV logs]$ jmap -histo 24527 | head -30
num #instances #bytes class name
----------------------------------------------
1: 31939 98883072 [C
2: 8594 9461992 [B
3: 30326 4256232 <constMethodKlass>
4: 30326 3892592 <methodKlass>
5: 2719 3226344 <constantPoolKlass>
6: 2450 1948704 <constantPoolCacheKlass>
7: 2719 1869200 <instanceKlassKlass>
8: 27599 662376 java.lang.String
9: 836 442968 <methodDataKlass>
10: 8215 394320 org.apache.tomcat.util.buf.ByteChunk
11: 3012 366720 java.lang.Class
12: 11257 360224 java.util.HashMap$Entry
13: 3417 273360 java.lang.reflect.Method
14: 6763 270520 java.util.TreeMap$Entry
15: 4326 260720 [S
16: 5410 259680 org.apache.tomcat.util.buf.MessageBytes
17: 6410 256400 org.apache.tomcat.util.buf.CharChunk
18: 4558 238352 [[I
19: 3347 211512 [Ljava.lang.Object;
20: 2144 189280 [I
21: 276 147936 <objArrayKlassKlass>
22: 948 142216 [Ljava.util.HashMap$Entry;
23: 2874 137952 java.util.HashMap
24: 621 89424 java.text.DecimalFormat
25: 2555 81760 java.util.concurrent.ConcurrentHashMap$HashEntry
26: 620 69440 java.util.GregorianCalendar
27: 1052 68936 [Ljava.lang.String;
其中:
[C is a char[]
[S is a short[]
[I is a int[]
[B is a byte[]
[[I is a int[][]
上面的输出中[C对象占用Heap这么多,往往跟String有关,String其内部使用final char[]数组来保存数据的。
jstat查看 gc实时执行情况
jstat命令命令格式:
jstat [Options] vmid [interval] [count]
命令参数说明:
Options,一般使用 -gcutil 或 -gc 查看gc 情况
pid,当前运行的 java进程号
interval,间隔时间,单位为秒或者毫秒
count,打印次数,如果缺省则打印无数次
Options 参数如下:
-gc:统计 jdk gc时 heap信息,以使用空间字节数表示
-gcutil:统计 gc时, heap情况,以使用空间的百分比表示
-class:统计 class loader行为信息
-compile:统计编译行为信息
-gccapacity:统计不同 generations(新生代,老年代,持久代)的 heap容量情况
-gccause:统计引起 gc的事件
-gcnew:统计 gc时,新生代的情况
-gcnewcapacity:统计 gc时,新生代 heap容量
-gcold:统计 gc时,老年代的情况
-gcoldcapacity:统计 gc时,老年代 heap容量
-gcpermcapacity:统计 gc时, permanent区 heap容量
示例
$ jstat -gc 12538 5000
每5 秒一次显示进程号为 12538的 java进成的 GC情况,结果如下图:
jstat -gcutil 70129 1000
由上图可知,新生代和老年代使用空间百分比接近100%,使用空间已经爆满了。
结果说明
标志 | 说明 |
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 | jdk1.8 metaspace已使用的占当前容量百分比 |
S0CMX | 年轻代中第一个survivor区的最大容量 (字节) |
S1CMX | 年轻代中第二个survivor区的最大容量 (字节) |
ECMX | 年轻代中Eden的最大容量 (字节) |
DSS | 当前需要survivor区的容量 (字节)(Eden区已满) |
TT | 持有次数限制 |
MTT | 最大持有次数限制 |
转载自:jmap输出
jmap -histo pid 输出的[C [B [I [S methodKlass constantPoolKlass含义