分析JAVA Application的内存使用时,jmap是一个很实用的轻量级工具。使用jmap可以查看heap空间的概要情况,粗略的掌握heap的使用情况。也可以生成heapdump文件,再使用jhat通过web浏览器具体分析内容中的对象和数据。
jmap是JDK自带的一个工具,非常小巧方便,其支持参数如下:
-heap 打印heap空间的概要,这里可以粗略的检验heap空间的使用情况。
jmap -heap PID
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
48
|
fs @inspur92 :~/test/llxdata/ 081005 /tmp$ jmap -heap 30774 Attaching to process ID 30774 , please wait... Debugger attached successfully. Server compiler detected. JVM version is 20.1 -b02 using thread-local object allocation. Parallel GC with 8 thread(s) Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 1073741824 ( 1024 .0MB) NewSize = 1310720 ( 1 .25MB) MaxNewSize = 17592186044415 MB OldSize = 5439488 ( 5 .1875MB) NewRatio = 2 SurvivorRatio = 8 PermSize = 21757952 ( 20 .75MB) MaxPermSize = 268435456 ( 256 .0MB) Heap Usage: PS Young Generation Eden Space: capacity = 353107968 ( 336 .75MB) used = 9083624 ( 8 .662818908691406MB) free = 344024344 ( 328 .0871810913086MB) 2.572477775409475 % used From Space: capacity = 2359296 ( 2 .25MB) used = 0 ( 0 .0MB) free = 2359296 ( 2 .25MB) 0.0 % used To Space: capacity = 2359296 ( 2 .25MB) used = 0 ( 0 .0MB) free = 2359296 ( 2 .25MB) 0.0 % used PS Old Generation capacity = 715849728 ( 682 .6875MB) used = 47522208 ( 45 .320709228515625MB) free = 668327520 ( 637 .3667907714844MB) 6.638573172720407 % used PS Perm Generation capacity = 40435712 ( 38 .5625MB) used = 40067528 ( 38 .21137237548828MB) free = 368184 ( 0 .35112762451171875MB) 99.08945834810575 % used |
以上的输出很简单,第四行起开始输出此进程的JAVA使用的环境。
Heap Configuration:指java应用启动时设置的JVM参数。像最大使用内存大小,年老代,年青代,持久代大小等。
Heap Usage:当时的heap实际使用情况。包括新生代、老生代和持久代。
其中新生代包括:Eden区的大小、已使用大小、空闲大小及使用率。Survive区的From和To同样。
有这个可以很简单的查看本进程的内存使用情况。
可以用于分析堆内存分区大小是否合理,新生代和老生代的大小分配是否合适等。
也许进程占用的总内存比较多,但我们在这里可以看到真正用到的并没有多少,很多都是"Free"。内存使用的堆积大多在老年代,内存池露始于此,所以要格外关心“Old Generation”。
jmap -histo PID
这里会生成一个类的统计报表,此表非常简单,如显示什么类有多少个实例,共占了多少字节等。如下:
fs@inspur92:~/test/llxdata/081005/tmp$ jmap -histo 30774
num #instances #bytes class name ---------------------------------------------- 1: 12077 37306240 [I 2: 8404 8913528 [B 3: 55627 8311744 <constMethodKlass> 4: 55627 7576152 <methodKlass> 5: 35982 6771360 [C 6: 4838 5536240 <constantPoolKlass> 7: 88849 4696992 <symbolKlass> 8: 4838 3735856 <instanceKlassKlass> 9: 4024 3334976 <constantPoolCacheKlass> 10: 4600 2201648 <methodDataKlass> 11: 35011 1120352 java.lang.String 12: 5286 549744 java.lang.Class 13: 6509 441272 [S 14: 7454 392128 [[I
其中关于I、B、C等的说明如下 Table 4.2.
BaseType Character | Type | Interpretation |
B | byte | signed byte |
C | char | Unicode character |
D | double | double-precision floating-point value |
F | float | single-precision floating-point value |
I | int | integer |
J | long | long integer |
L<classname>; | reference | an instance of class de><classname>de> |
S | short | signed short |
Z | boolean | de>truede> or de>falsede> |
[ | reference | one array dimension |
jmap -permstat
打印一些持久代上的内存使用状态,有“活”的,有“死”的。
class_loader classes bytes parent_loader alive? type <bootstrap> 2099 12780072 null live <internal> 0x00000000c069dc58 1 1968 0x00000000c017e968 dead sun/reflect/DelegatingClassLoader@0x00000000b00685b0 0x00000000c05c37d8 1 2008 0x00000000c017e968 dead sun/reflect/DelegatingClassLoader@0x00000000b00685b0 0x00000000c069d900 1 1968 0x00000000c017e968 dead sun/reflect/DelegatingClassLoader@0x00000000b00685b0
不常用。
-heap:format=b
产生一个HeapDump文件,此为生成heapdump文件的重要参数。 例:jmap -heap:format=b 2657 会产生一个heap.bin的heapdump文件。 需要注意的是,此生成heapdump的参数为JDK1.5,在1.6中的格式为: jmap -dump:live,format=b,file=xxx 2657 这里更加强大一些,可以指定是存活的对象,还有生成heapdump的文件名。
当被测应用使用内容较大时(4G以上),dump需要花费较长时间,很可能导致dump失败。
dump下来的文件结合jhat进行分析会更方便。
jhat
jhat是一个Java堆复制浏览器。这个工具分析Java堆复制文件(例如,由上面的"jmap -dump"所产生的)。Jhat启动一个允许堆中的对象在web浏览器中进行分析的web服务器。这个工具并不是想用于应用系统中而是用于"离线"分析。"jhat工具是平台独立的",其意思是,它可以被用来观察在任何平台上所产生的堆复制。例如,我们有可能在Linux系统上使用jhat来观察一个 在Solaris OS上所产生的堆复制。
把本机的java内存映像导出到heap.dmp中,其中PID为java进程的ID号。 jmap -dump:live,format=b,file=heap.dmp PID
导出后的映像文件可以用jhat来进行分析,-J是向java虚拟机传一个参数,如-mx768m是指定虚拟机可用最大的内存为768M。如果映像文件很大,你要指定一个很大的值,否则在分析过程中就会有OutOfMemeryError的错误。
jhat -J-mx768m -port <端口号:默认为7000> heap.dmp