原文链接:http://my.oschina.net/freegarden/blog/286372
摘要
Oracle JVM自带了一些工具,观察java程序的运行,用于排错调优。正文将会对 jConsole 、jvisualvm 和 jmap 进行简单介绍。
JConsole
JConsole 是一个内置 Java 性能分析器,可以从命令行或在 GUI shell 中运行。可以轻松地使用 JConsole来监控 Java 应用程序性能和跟踪 Java 中的代码。
1- 启动
使 JDK 在 PATH 上,从命令行启动,运行 jconsole
2- 连接
2.1- 本地连接
2.2- 远程连接
无认证连接设置
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8888
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
图示如下
还有一种启动方式:jconsole.exe 192.168.3.228:8888
3- 性能分析
3.1- 概述: Displays overview information about the Java VM and monitored values.
对着图点击右键可以保存数据到CSV文件,以后可以使用其他工具来分析这些数据。
3.2- 内存: 显示内存使用信息
查看堆内存,非堆内存,内存池的状况总体内存的分配和使用情况以及不同的GC进行垃圾回收的次数和时间。
3.3- 线程: 显示线程使用信息
3.4- 类: 显示类装载信息
3.5- VM摘要: 显示java VM信息
3.6- MBeans: 显示 MBeans
jvisualvm
升级版的jConsole。
从命令行启动,运行 jvisualvm 。
jmap
用来显示Java进程的内存映射。
1-默认视图
查看连接到进程里的本地类库。
[[email protected]192 ~]$ jmap 26001
Attaching to process ID 26001, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 17.0-b16
0x00683000 139K /lib/ld-2.12.so
0x006a9000 1845K /lib/libc-2.12.so
0x0083d000 197K /lib/libm-2.12.so
0x00869000 19K /lib/libdl-2.12.so
0x00870000 130K /lib/libpthread-2.12.so
0x008a3000 40K /lib/librt-2.12.so
0x04103000 113K /lib/libnsl-2.12.so
0x08048000 46K /usr/java/jdk1.6.0_21/bin/java
0x4ef5f000 36K /usr/java/jdk1.6.0_21/jre/lib/i386/libnio.so
0x53402000 4K /usr/java/jdk1.6.0_21/jre/lib/i386/librmi.so
0xb6c09000 93K /usr/java/jdk1.6.0_21/jre/lib/i386/libnet.so
0xb6c1d000 33K /usr/java/jdk1.6.0_21/jre/lib/i386/libmanagement.so
0xb6c75000 57K /lib/libnss_files-2.12.so
0xb6c86000 74K /usr/java/jdk1.6.0_21/jre/lib/i386/libzip.so
0xb6c9f000 184K /usr/java/jdk1.6.0_21/jre/lib/i386/libjava.so
0xb6d15000 9452K /usr/java/jdk1.6.0_21/jre/lib/i386/server/libjvm.so
0xb78b5000 37K /usr/java/jdk1.6.0_21/jre/lib/i386/jli/libjli.so
0xb78c5000 37K /usr/java/jdk1.6.0_21/jre/lib/i386/native_threads/libhpi.so
0xb78ce000 55K /usr/java/jdk1.6.0_21/jre/lib/i386/libverify.so
[[email protected]192 ~]$
2-堆视图
堆大小是年轻代、年老代加上PermGen区总和。年轻代内部有伊甸园和幸存者乐园。
[[email protected]192 ~]$ jmap -heap 26001
Attaching to process ID 26001, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 17.0-b16
using thread-local object allocation.
Parallel GC with 2 thread(s)
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB)
NewSize = 1048576 (1.0MB)
MaxNewSize = 4294901760 (4095.9375MB)
OldSize = 4194304 (4.0MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 16777216 (16.0MB)
MaxPermSize = 536870912 (512.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 266665984 (254.3125MB)
used = 219310160 (209.1504669189453MB)
free = 47355824 (45.16203308105469MB)
82.24152053829258% used
From Space:
capacity = 34734080 (33.125MB)
used = 34713344 (33.105224609375MB)
free = 20736 (0.019775390625MB)
99.94030070754717% used
To Space:
capacity = 46268416 (44.125MB)
used = 0 (0.0MB)
free = 46268416 (44.125MB)
0.0% used
PS Old Generation
capacity = 715849728 (682.6875MB)
used = 591219088 (563.8304595947266MB)
free = 124630640 (118.85704040527344MB)
82.58983203804472% used
PS Perm Generation
capacity = 123863040 (118.125MB)
used = 122851872 (117.16067504882812MB)
free = 1011168 (0.964324951171875MB)
99.18364025297619% used
[[email protected]192 ~]$
以上信息看不到堆内的信息,要知道内存都到哪了去了,就得使用柱状视图。
3-柱状视图
jmap使用类型内部名称。如:字符数组会写成 [C 。
[xinli@192 ~]$ jmap -histo 26001 | head -30
num #instances #bytes class name
----------------------------------------------
1: 2433674 208875632 [C
2: 72266 161710576 [B
3: 2288352 54920448 java.lang.String
4: 295753 36620048 <constMethodKlass>
5: 795406 35750608 [Ljava.lang.Object;
6: 295753 23665800 <methodKlass>
7: 803901 19293624 java.util.HashMap$Entry
8: 584375 18700000 java.util.LinkedHashMap$Entry
9: 375345 18016560 org.hibernate.collection.PersistentSet
10: 249156 16440472 [I
11: 199796 15983680 java.lang.reflect.Method
12: 98625 15092552 [Ljava.util.HashMap$Entry;
13: 375797 15031880 org.hibernate.engine.CollectionEntry
14: 22720 14800808 <constantPoolKlass>
15: 805673 12890768 java.lang.Long
16: 375797 12025504 org.hibernate.engine.CollectionKey
17: 481249 11549976 java.sql.Timestamp
18: 155849 11221128 VideoCategory
19: 87492 11198976 VideoProgramMenu
20: 22720 10706552 <instanceKlassKlass>
21: 18790 9374096 <constantPoolCacheKlass>
22: 163064 9131584 org.codehaus.groovy.runtime.metaclass.MetaMethodIndex$Entry
23: 166641 9002408 <symbolKlass>
24: 148902 8338512 org.codehaus.groovy.runtime.metaclass.MetaMethodIndex$Entry
25: 320357 7999624 [Ljava.lang.String;
26: 331095 7946280 java.sql.Date
27: 472017 7552272 org.hibernate.util.IdentityMap$IdentityKey
[xinli@192 ~]$
以上只是输出的一部分。输出中有很多占用内存的 [C 实体。
存货对象的查看:
[xinli@192 ~]$ jmap -histo:live 26001 | head -5
num #instances #bytes class name
----------------------------------------------
1: 1891237 111818968 [C
2: 1903147 45675528 java.lang.String
比较一下字符数据是不是降低了不少,说明有好多等待回收的垃圾。