tomcat工程,运行一段时间卡死。日志报Perm内存溢出。
记录一下排查过程,以及解决思路
查看堆区内存使用情况
jmap -heap pid
Attaching to process ID 14735, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.65-b04
using thread-local object allocation.
Parallel GC with 8 thread(s) #采用并行GC策略
#java heap配置
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 8392802304 (8004.0MB)
NewSize = 1310720 (1.25MB)
MaxNewSize = 17592186044415 MB
OldSize = 5439488 (5.1875MB) #老生代大小
NewRatio = 2
SurvivorRatio = 8
PermSize = 21757952 (20.75MB) #JVM初始分配的非堆内存
MaxPermSize = 85983232 (82.0MB) #永久带最大空间
G1HeapRegionSize = 0 (0.0MB)
#堆实际使用情况
Heap Usage:
PS Young Generation
Eden Space:
capacity = 2796552192 (2667.0MB)
used = 0 (0.0MB)
free = 2796552192 (2667.0MB)
0.0% used
From Space:
capacity = 524288 (0.5MB)
used = 0 (0.0MB)
free = 524288 (0.5MB)
0.0% used
To Space:
capacity = 524288 (0.5MB)
used = 0 (0.0MB)
free = 524288 (0.5MB)
0.0% used
PS Old Generation
capacity = 5595201536 (5336.0MB)
used = 87076912 (83.04301452636719MB)
free = 5508124624 (5252.956985473633MB)
1.5562783831777958% used
PS Perm Generation
capacity = 85983232 (82.0MB)
used = 85983080 (81.9998550415039MB)
free = 152 (1.4495849609375E-4MB)
99.99982322134623% used
31026 interned Strings occupying 3399648 bytes.
对一些配置的定义,在此稍作解释;
- MinHeapFreeRatio
指定 jvm heap 在使用率小于 n 的情况下 ,heap 进行收缩 ,Xmx==Xms 的情况下无效 , 如 :- - XX:MinHeapFreeRatio=30
指定 jvm heap 在使用率大于 n 的情况下 ,heap 进行扩张 ,Xmx==Xms 的情况下无效 , 如 :-XX:MaxHeapFreeRatio=70 - NewSize/MaxNewSize:定义YOUNG段的尺寸,NewSize为JVM启动时YOUNG的内存大小;MaxNewSize为最大可占用的YOUNG内存大小。在用户生产环境上一般将这两个值设为相同,以减少运行期间系统在内存申请上所花的开销。
- NewRatio=2 年轻代(包括1个Eden和2个Survivor区)与年老代的比值。表示年轻代比年老代为1:2。
- SurvivorRatio=8:设置年轻代中Eden区与Survivor区的比值。表示2个Survivor区(JVM堆内存年轻代中默认有2个大小相等的Survivor区)与1个Eden区的比值为2:4,即1个Survivor区占整个年轻代大小的1/6。
上面是java进程内存的使用情况。可以看到永久带满了,而其他区域使用率不高。
查看gc情况
jstat -gc -h 10 14735 1000
其中
- C结尾的是Capacity
- U结尾的是Used
- S0为年轻代中第一个survivor
- S1为年轻代中第二个survivor
- E为年轻代中Eden
- O为老年代
- P为永久带
- YGC从应用程序启动到采样时年轻代中gc次数
- YGCT从应用程序启动到采样时年轻代中gc所用时间
单位为KB
…从上图可以看出。在1秒内,系统做了8次Full GC。
这样看,原因已经很明显了,Perm区容量太小,导致频繁Full GC,最终Full GC也无法释放足够空间时,报 java.lang.OutOfMemoryError: PermGen space。而堆区内存过大,存在浪费现象。因此,解决办法是调大Perm区内存,减小堆区内存。