Swen 2010-12-28
Java语言不允许开发者管理内存,内存是靠jvm 统一管理,的内存对开发者来说是透明的。但有时需要了解内存内部活动,就需要通过一些工具实现。介绍两个SUN 的JDK中的工具 jmap jstat
一.jmap
1. jmap -heap pid
查看java 堆(heap)使用情况
using thread-local object allocation.
ParallelGCwith4thread(s)//GC方式
HeapConfiguration://堆内存初始化配置
MinHeapFreeRatio=40//对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default40)
MaxHeapFreeRatio=70//对应jvm启动参数-XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default70)
MaxHeapSize=512.0MB//对应jvm启动参数-XX:MaxHeapSize=设置JVM堆的最大大小
NewSize=1.0MB//对应jvm启动参数-XX:NewSize=设置JVM堆的‘新生代’的默认大小
MaxNewSize=4095MB//对应jvm启动参数-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小
OldSize=4.0MB//对应jvm启动参数-XX:OldSize=<value>:设置JVM堆的‘老生代’的大小
NewRatio=8//对应jvm启动参数-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
SurvivorRatio=8//对应jvm启动参数-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值
PermSize=16.0MB//对应jvm启动参数-XX:PermSize=<value>:设置JVM堆的‘永生代’的初始大小
MaxPermSize=64.0MB //对应jvm启动参数-XX:MaxPermSize=<value>:设置JVM堆的‘永生代’的最大大小Heap Usage: //堆内存分步
PSYoungGeneration
EdenSpace://Eden区内存分布
capacity=20381696(19.4375MB)//Eden区总容量
used=20370032(19.426376342773438MB)//Eden区已使用
free=11664(0.0111236572265625MB)//Eden区剩余容量
99.94277218147106%used//Eden区使用比率
FromSpace://其中一个Survivor区的内存分布
capacity=8519680(8.125MB)
used=32768(0.03125MB)
free=8486912(8.09375MB)
0.38461538461538464%used
ToSpace://另一个Survivor区的内存分布
capacity=9306112(8.875MB)
used=0(0.0MB)
free=9306112(8.875MB)
0.0%used
PSOldGeneration//当前的Old区内存分布
capacity=366280704(349.3125MB)
used=322179848(307.25464630126953MB)
free=44100856(42.05785369873047MB)
87.95982001825573%used
PSPermGeneration//当前的“永生代”内存分布
capacity=32243712(30.75MB)
used=28918584(27.57891082763672MB)
free=3325128(3.1710891723632812MB)
89.68751488662348% used2. jmap -histo pid
查看堆内存(histogram)中的对象数量,大小
num #instances #bytes class name
序号 实例个数 字节数 类名
----------------------------------------------
1:3174877107858256[C
2:317149976115976java.lang.String
3:139788438122240[B
4:21469037785440com.tongli.book.form.Book
5:10734518892720com.tongli.book.form.Book
6:6564513953440[Ljava.lang.Object;
7:596277648416<constMethodKlass>
8:2918527004448java.util.HashMap$Entry
9: 107349 6871176 [[B..........
total 9150732 353969416
3. jmap - dump pid
将内存使用的详细情况输出到文件
map -dump:format=b,file= m.dat pid
用jhat命令可以参看 jhat -port 5000 m.dat 在浏览器中访问:http://localhost:5000/ 查看详细信息
sun 官方文档 http://download.oracle.com/javase/1.5.0/docs/tooldocs/share/jmap.html
二、jstat
1. jstat -gc pid
可以显示gc的信息,查看gc的次数,及时间。
其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。
2.jstat -gccapacity pid
可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小,
如:PGCMN显示的是最小perm的内存使用量,PGCMX显示的是perm的内存最大使用量,
PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。
其他的可以根据这个类推, OC是old内纯的占用量。
3.jstat -gcutil pid
统计gc信息统计。
4.jstat -gcnew pid
年轻代对象的信息。
5.jstat -gcnewcapacity pid
年轻代对象的信息及其占用量。
6.jstat -gcold pid
old代对象的信息。
7.stat -gcoldcapacity pid
old代对象的信息及其占用量。
8.jstat -gcpermcapacity pid
perm对象的信息及其占用量。
9.jstat -class pid
显示加载class的数量,及所占空间等信息。 10.jstat -compiler pid
显示VM实时编译的数量等信息。
11.stat -printcompilation pid
当前VM执行的信息。
一些术语的中文解释:
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代已使用的占当前容量百分比
S0CMX:年轻代中第一个survivor(幸存区)的最大容量 (字节)
S1CMX :年轻代中第二个survivor(幸存区)的最大容量 (字节)
ECMX:年轻代中Eden(伊甸园)的最大容量 (字节)
DSS:当前需要survivor(幸存区)的容量 (字节)(Eden区已满)
TT: 持有次数限制
MTT : 最大持有次数限制
sun 官方文档 http://download.oracle.com/javase/1.5.0/docs/tooldocs/share/jstat.html
另附:jvm启动参数
一:JVM启动参数共分为三类:
其一是标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容;
其二是非标准参数(-X),指的是JVM底层的一些配置参数,这些参数在一般开发中默认即可,不需要任何配置。但是在生产环境中,并不保证所有jvm实现都满足,所以为了提高性能,往往需要调整这些参数,以求系统达到最佳性能。另外这些参数不保证向后兼容,也即是说“如有变更,恕不在后续版本的JDK通知”(这是官网上的原话);
其三是非Stable参数(-XX),这类参数在jvm中是不稳定的,不适合日常使用的,后续也是可能会在没有通知的情况下就直接取消了,需要慎重使用。
二:而JVM内存又可分为三个主要的域:
新域、旧域以及永久域。JVM生成的所有新对象放在新域中。一旦对象经历了一定数量的垃圾收集循环后,便进入旧域。而在永久域中是用来存储JVM自己的反射对象的,如class和method对象,而且GC(GarbageCollection)不会在主程序运行期对永久域进行清理。其中新域和旧域属于堆,永久域是一个独立域并且不认为是堆的一部分。
三:各主要参数的作用如下:
-Xms:设置jvm内存的初始大小
-Xmx:设置jvm内存的最大值
-Xmn:设置新域的大小(这个似乎只对jdk1.4来说是有效的,后来就废弃了)
-Xss:设置每个线程的堆栈大小(也就是说,在相同物理内存下,减小这个值能生成更多的线程)
-XX:NewRatio:设置新域与旧域之比,如-XX:NewRatio=4就表示新域与旧域之比为1:4
-XX:NewSize:设置新域的初始值
-XX:MaxNewSize:设置新域的最大值
-XX:MaxPermSize:设置永久域的最大值
-XX:SurvivorRatio=n:设置新域中Eden区与两个Survivor区的比值。(Eden区主要是用来存放新生的对象,而两个Survivor区则用来存放每次垃圾回收后存活下来的对象)