转自http://ldbjakyo.iteye.com/blog/759586
JVM内存异常例子
java.lang.OutOfMemoryError: PermGen space
permanent space持久空间: 用于类和方法对象的存储。spring在AOP时使用CBLIB会动态产生很多类,JSP页面, Java反射类,当类太多,超过MaxPermSize的时候,就会抛出此异常。
参数问题可以设置jvm启动参数: PermSize, MaxPermSize。
如果是程序问题就要进行内存分析。
网上对Perm讨论的比较火热,有相当多的人认为这是JDK的一个至今未解决的BUG,因为Perm里存储的东西永远不会被JVM垃圾回收的,这个问题已经提出多年,但未得到SUN的解决。
java.lang.OutOfMemoryError: Java heap space
eden space使用率100%,总是被占满,参数问题可以设置jvm启动参数: Xms, Xmx。
如果是程序问题就要进行内存分析。
jdk里包括一个查看JVM状态的工具
jstat -gcutil pid号 1000 20
这里涉及到PID 关于pid 的查看 请查看我的 另外一篇 文章
http://ldbjakyo.iteye.com/admin/blogs/759533
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:用于垃圾回收的总时间(单位秒) |
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频繁发生。 |
JDK自带的JVM查看分析工具jps、jmap、jstat、jconsole
jps
Java进程查看工具,实际上它和Unix/Linux上面的ps命令的功能差不多
jmap
jmap是一个可以输出所有内存中对象的工具.
* -dump:format=b,file=<filename> 转存堆内存到本地文件。
* -histo 打印堆里每个类的情况,包含内存占用大小、对象数量及完整类名。VM的内部类以"*"开头。
例子:
- jmap -histo pid号>log文件名
- jmap -dump: file=a.hprof pid号
查看log文件
Object Histogram: |
Size Count Class description |
------------------------------------------------------- |
21396040 135280 * ConstMethodKlass |
14231448 11002 * ConstantPoolKlass |
14076608 135280 * MethodKlass |
13120872 144660 char[] |
8795640 11002 * InstanceKlassKlass |
8070520 15045 byte[] |
8040592 147990 * SymbolKlass |
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; |
... |
#instance是对象的实例个数
#bytes是总占用的字节数
class name对应的就是Class文件里的class的标识
B代表byte
C代表char
D代表double
F代表float
I代表int
J代表long
Z代表boolean
前边有[代表数组,[I 就相当于int[]
对象用[L+类名表示
关于ConstMethodKlass
http://forums.sun.com/thread.jspa?threadID=760714
如果你看到ConstMethodKlass增加, ConstantPoolKlass等你载入“过度“数类(顺便说一句, ConstantPoolXXX对象用于存储有关ConstantPool的信息。class文件- 请参阅http://java.sun.com/docs / books/vmspec/2nd-edition/html/ConstantPool.doc.html 。同样, ConstMethodKlass存储方法的字节码等。) 。可能是因为您的应用程序加载的类地段(甚至可能是那些很多都是动态生成- 例如,JSP页面, Java反射类等)。一个可能的“修复“,就是要增加空间 MaxPermSize选项。
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
jconsole
一个java GUI监视工具,可以以图表化的形式显示各种数据。并可通过远程连接监视远程的服务器VM。
Dump出内存
(1)Jconsole 打开后选择dumpHeap, 输入参数p0,p1;p0表示dump出来的文件路径,后缀为.hprof; p1设为true,表示只分析活着的对象。
(2)jmap -dump:file=a.hprof pid
其他内存分析工具
分析Java内存对象的工具,如收费的工具有jprofiler, 而像Eclipse MAT则是优秀的内存对象分析开源工具.它们对于分析内存溢出问题非常有用。以下是一个安装使用Eclipse MAT的简单例子。
(1)装一个Eclipse的内存分析插件MAT
http://download.eclipse.org/technology/mat/latest/update-site/
(2)切换到Memory Analysis模式
通过File > Open Heap Dump....查看dump出来的文件