您的位置:首页 > 其它

探究JVM内存泄露

2011-05-30 14:27 204 查看
WEB服务总是莫名其妙的运行一段时间后JVM直接OutOfMemory错误,内存泄漏的问题不容易查找,本文就一些查找内存泄露基本知识做个总结,未涉及到具体案例的分析。
1
JVM内存异常的数据显示

1.1
java.lang.OutOfMemoryError: PermGen space异常的例子


Heap

PSYoungGen total 44928K, used 916K [0x4e3c0000, 0x50fe0000, 0x51b10000)

eden space 44736K, 2% used [0x4e3c0000,0x4e4a5318,0x50f70000)

from space 192K, 0% used [0x50f70000,0x50f70000,0x50fa0000)

to space 192K, 0% used [0x50fb0000,0x50fb0000,0x50fe0000)

PSOldGen total 453312K, used 125529K [0x32910000, 0x4e3c0000, 0x4e3c0000)

object space 453312K, 27% used [0x32910000,0x3a3a6498,0x4e3c0000)

PSPermGen total 65536K, used 65535K [0x2e910000, 0x32910000, 0x32910000)

object space 65536K, 99% used [0x2e910000,0x3290fff8,0x32910000)
permanent space持久空间:
用于类和方法对象的存储。spring在AOP时使用CBLIB会动态产生很多类,当类太多,超过MaxPermSize的时候,就会抛出此异常。参数问题可以设置jvm启动参数:
PermSize, MaxPermSize。程序问题就要进行内存分析了,详见下文。
1.2
java.lang.OutOfMemoryError: Java heap space异常的例子


Heap

PSYoungGen total 88320K, used 67673K [0x44880000, 0x4ba40000, 0x4ba40000)

eden space 61952K, 100% used [0x44880000,0x48500000,0x48500000)

from space 26368K, 21% used [0x48500000,0x48a96490,0x49ec0000)

to space 24512K, 16% used [0x4a250000,0x4a6283e0,0x4ba40000)

PSOldGen total 932096K, used 582090K [0x0ba40000, 0x44880000, 0x44880000)

object space 932096K, 62% used [0x0ba40000,0x2f2b2a78,0x44880000)

PSPermGen total 131072K, used 35124K [0x03a40000, 0x0ba40000, 0x0ba40000)

object space 131072K, 26% used [0x03a40000,0x05c8d330,0x0ba40000)
eden space使用率100%,总是被占满,参数问题可以设置jvm启动参数:
Xms, Xmx。程序问题就要进行内存分析了,详见下文。
1.3
查看jvm内存状态:

jstat -gcutil pid 1000 20
异常情况的例子
jstat -gcutil pid 1000 20

S0 S1 E O P YGC YGCT FGC FGCT GCT

0.00 0.00 99.99 82.51 53.11 2409 1.205 10117 7250.393 7251.598

0.00 0.00 83.42 82.55 53.10 2409 1.205 10118 7252.650 7253.855

0.00 0.00 56.06 82.46 53.10 2410 1.205 10120 7254.467 7255.672

0.00 0.00 32.11 82.55 53.10 2411 1.205 10121 7256.673 7257.877

0.00 0.00 99.99 82.55 53.10 2412 1.205 10123 7257.026 7258.231

0.00 0.00 76.00 82.50 53.10 2412 1.205 10124 7259.241 7260.446
这个数据显示Full GC频繁发生。
正常情况的例子

S0 S1 E O
P YGC YGCT FGC
FGCT GCT

0.00 0.00 0.24 55.39
99.60 171 0.667 1339
393.364 394.031

0.00 0.00 0.24 55.39
99.60 171 0.667 1339
393.364 394.031

0.00 0.00 0.24 55.39
99.60 171 0.667 1339
393.364 394.031

0.00 0.00 0.24 55.39
99.60 171 0.667 1339
393.364 394.031

0.00 0.00 0.24 55.39
99.60 171 0.667 1339
393.364 394.031

0.00 0.00 0.24 55.39
99.60 171 0.667 1339
393.364 394.031
参数含义:

S0:Heap上的 Survivor space 0
段已使用空间的百分比

S1:Heap上的 Survivor space 1
段已使用空间的百分比

E: Heap上的 Eden space
段已使用空间的百分比

O: Heap上的 Old space
段已使用空间的百分比

P: Perm space
已使用空间的百分比

YGC:从程序启动到采样时发生Young GC的次数

YGCT:Young GC所用的时间(单位秒)

FGC:从程序启动到采样时发生Full GC的次数

FGCT:Full GC所用的时间(单位秒)

GCT:用于垃圾回收的总时间(单位秒)

2
Dump出内存

2.1
找出要dump的线程pid


在windows下,使用tasklist
在Linux下,使用ps
–aux
2.2
Dump出内存使用详情

可以通过命令:

jmap -dump:file=a.hprof pid
也可以通过jconsole的图形界面操作。

在命令行键入:jconsole
Jconsole
打开后在造作下选择dumpHeap,
输入参数p0,p1;p0表示dump出来的文件路径,后缀为.hprof;
p1设为true,表示只分析活着的对象。



3
使用内存分析工具

目前有很多用来分析Java内存对象的工具,如收费的工具有jprofiler,
而像Eclipse MAT则是优秀的内存对象分析开源工具.它们对于分析内存溢出问题非常有用。以下是一个安装使用Eclipse
MAT的简单例子。

3.1
装一个Eclipse的内存分析插件MAT

http://download.eclipse.org/technology/mat/latest/update-site/

3.2
切换到Memory Analysis模式





3.3
通过File > Open Heap Dump....查看dump出来的文件




4
JDK自带的JVM查看分析工具jps、jmap、jstat、jconsole

4.1
jps

Java进程查看工具,实际上它和Unix/Linux上面的ps命令的功能差不多

4.2
jmap

jmap是一个可以输出所有内存中对象的工具.
* -dump:format=b,file=<filename>
转存堆内存到本地文件。

* -histo 打印堆里每个类的情况,包含内存占用大小、对象数量及完整类名。VM的内部类以"*"开头。
例子:

jmap -histo pid>a.log
jmap -dump: file=a.hprof pid
查看a.log

num #instances #bytes class name

--------------------------------------

1: 427398 14458448 [I

2: 178798 6830216 [C

3: 50278 6668512 <constMethodKlass>

4: 179924 4318176 java.lang.String

5: 50278 4026648 <methodKlass>

6: 15244 3894200 [B

7: 47809 1773776 [Ljava.lang.Object;

...

Total 1645187 81806088
说明:
#instance是对象的实例个数

#bytes是总占用的字节数

class name对应的就是Class文件里的class的标识

B代表byte

C代表char

D代表double

F代表float

I代表int

J代表long

Z代表boolean

前边有[代表数组,[I
就相当于int[]
对象用[L+类名表示
4.3
jstat

jstat是vm的状态监控工具,监控的内容有类加载、运行时编译及GC。
使用时,需加上查看进程的进程id,和所选参数。以下详细介绍各个参数的意义。

jstat -class pid:显示加载class的数量,及所占空间等信息。

jstat -compiler pid:显示VM实时编译的数量等信息。

jstat -gc pid:可以显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young
gc的次数,young gc的时间,full gc的次数,full
gc的时间,gc的总时间。

jstat -gccapacity:可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小,如:PGCMN显示的是最小perm的内存使用量,PGCMX显示的是perm的内存最大使用量,PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。其他的可以根据这个类推,
OC是old内纯的占用量。

jstat -gcnew pid:new对象的信息。

jstat -gcnewcapacity pid:new对象的信息及其占用量。

jstat -gcold pid:old对象的信息。

jstat -gcoldcapacity pid:old对象的信息及其占用量。

jstat -gcpermcapacity pid: perm对象的信息及其占用量。

jstat -util pid:统计gc信息统计。

jstat -printcompilation pid:当前VM执行的信息。

除了以上一个参数外,还可以同时加上
两个数字,如:jstat -printcompilation 3024 250 6是每250毫秒打印一次,一共打印6次,还可以加上-h3每三行显示一下标题。

例子:

jstat -gcutil pid 1000 20
4.4
jconsole

一个java GUI监视工具,可以以图表化的形式显示各种数据。并可通过远程连接监视远程的服务器VM。

转载:http://blog.csdn.net/winniepu/article/details/4934764
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: