英文地址:
http://java.sun.com/javase/6/docs/technotes/tools/share/jmap.html
jmap可以打印给定的jvm进程或远程debug服务的共享对象的内存映射图或者详细的heap内存信息. 假如给定的jvm是运行在64位模式,那么你需要指定-J-d64参数,例如: jmap -J-d64 -heap pid
jmap在windows平台上,只能使用的形式如下:
jmap -dump: pid
和
jmap -histo[:live] pid
jmap的命令如下:
jmap [ option ] pid
jmap [ option ] executable core
jmap [ option ] [server-id@]remote-hostname-or-IP
parameters
options
打印jvm中加载的每个共享对象,起始地址,映射的内存大小,共享对象文件的全路径.
-dump:[live,]format=b,file=
输出jvm的heap内容到文件,并使用hprof二进制形式. live子选项如果指定,那么只输出活的对象到文件.
-finalizerinfo
打印正等待回收的对象的信息
-histo[:live]
打印每个class的实例数量,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 假如live子参数加上后,只统计活的对象数量.
-permstat
打印classload和jvm heap持久层的信息. 包括每个classloader的名字,活跃性,地址,父classloader和加载的class数目. 另外,内部String的数量和占用内存数也会打印出来.
-F
强制.在pid没有相应的时候使用-dump或者-histo参数. 在这个模式下,live子参数无效.
-h | -help
打印帮助信息
-J
传递参数给jmap启动的jvm.
pid
需要被打印配置信息的java进程id,可以用jps查询.
executable
Java executable from which the core dump was produced.
(可能是产生core dump的java可执行程序)
core
将被打印信息的core dump文件
remote-hostname-or-IP
远程debug服务的主机名或ip
server-id
唯一id,假如一台主机上多个远程debug服务
最近在搞64位系统的升级,搞了一台放到正是环境的pool中,在原先的32位下,我们定义的heap size是1024m,其中permsize是96m,实用70m左右.同样的配置在64位jvm里,Perm Generation直接暴掉,于是扩大至128m,实用稳定在108m左右,这里的原因是64位系统下,object占用了更大的内存,可以用 -XX:+UseCompressedOops参数压缩(java6好像还不支持),但是我们没有使用.
经过前几天的运行,系统还算稳定(经过上午,下午两个网上流量高峰期).昨天发布后,我在晚上19点半左右enable这台测试机,早上到了公司,观察了一下运行情况.10点中左右发现jvm异常.
jstat -gcutil 22671 1000 1000
显示如下:
1
2
3
4
5
6
7
| S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 0.00 100.00 100.00 84.71 17079 392.748 586 960.447 1353.195
0.00 0.00 100.00 100.00 84.71 17079 392.748 587 962.212 1354.960
0.00 0.00 100.00 100.00 84.71 17079 392.748 587 962.212 1354.960
0.00 0.00 100.00 100.00 84.71 17079 392.748 588 963.992 1356.740
0.00 0.00 100.00 100.00 84.71 17079 392.748 588 963.992 1356.740
0.00 0.00 100.00 100.00 84.58 17079 392.748 589 965.907 1358.655 |
jmap 22671
显示如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| Attaching to process ID 22671, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 10.0-b23
using thread-local object allocation.
Parallel GC with 8 thread(s)
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB)
NewSize = 268435456 (256.0MB)
MaxNewSize = 268435456 (256.0MB)
OldSize = 5439488 (5.1875MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 134217728 (128.0MB)
MaxPermSize = 134217728 (128.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 126615552 (120.75MB)
used = 126615552 (120.75MB)
free = 0 (0.0MB)
100.0% used
From Space:
capacity = 52494336 (50.0625MB)
used = 0 (0.0MB)
free = 52494336 (50.0625MB)
0.0% used
To Space:
capacity = 70909952 (67.625MB)
used = 0 (0.0MB)
free = 70909952 (67.625MB)
0.0% used
PS Old Generation
capacity = 805306368 (768.0MB)
used = 804698024 (767.4198379516602MB)
free = 608344 (0.5801620483398438MB)
99.92445806662242% used
PS Perm Generation
capacity = 134217728 (128.0MB)
used = 113520112 (108.26121520996094MB)
free = 20697616 (19.738784790039062MB)
84.57907438278198% used |
在上面显示的数据中,full gc频繁发生,占用了大量的资源
eden Space和Old Generation的heap多已经使用100%
于是dump jvm
jmap -dump:file=dump_run.hprof 22671
java6和64位下dump速度比在java5和32下快很多,瞬间完成.拷贝到本地,在eclipse里用mat插件(http://download.eclipse.org/technology/mat/0.7/update-site/)查看,立即找到问题,如图示:

昨日发布的一个变更设计有问题,出现了多份实例,没份实例占21m,共占用300m左右的内存.同样的情况在32位机器上表现的没有那么糟糕,似乎一切运行正常,看来64位的指针和对象占用heap单位比32下大很多.