内存划分
Java虚拟机规范,JVM将内存划分为:New、Tenured、Perm。其中New和Tenured属于堆内存,堆内存会从JVM启动参数(-Xmx:3G)指定的内存中分配,一般来讲:heap=Y+O,Sun推荐Y=heap*(3/8);P是额外的值,P不属于堆内存,由虚拟机直接分配,但可以通过-XX:PermSize -XX:MaxPermSize 等参数调整其大小。
- New(年轻代)
|
|
- Tenured(年老代)
|
|
- 永久代(Perm)
|
|
- New(年轻代
E+S0+S1=Y
)分为:- Eden:Eden用来存放JVM刚分配的对象
- Survivor1
- Survivro2:两个Survivor空间一样大,当Eden中的对象经过垃圾回收没有被回收掉时,会在两个Survivor之间来回Copy,当满足某个条件,比如Copy次数,就会被Copy到Tenured。显然,Survivor只是增加了对象在年轻代中的逗留时间,增加了被垃圾回收的可能性。
内存参数说明
|
|
一些工具的使用
jps (Java Virtual Machine Process Status Tool)
- 查看所有jvm进程id
|
|
jmap (Java Memory Map)
- dump该pid的内存使用情况(二进制文件,需要借助工具MAT-Memory Analysis Tool 或者 jhat-Java Heap Analysis Tool分析)
|
|
- 打印每个class的实例数目统计排行,内存占用,类全名信息
|
|
- 打印heap的概要信息
|
|
详细
-dump:[live,]format=b,file=<filename> 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件. -finalizerinfo 打印正等候回收的对象的信息. -heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况. -histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量. -permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来. -F 强迫.在pid没有相应的时候使用-dump或者-histo参数. 在这个模式下,live子参数无效. -h | -help 打印辅助信息 -J 传递参数给jmap启动的jvm.
jstack(Java Stack Trace)
dump该pid下的堆栈信息
|
|
jstat (Java Virtual Machine Statistics Monitoring Tool)
Jstat用于监控基于HotSpot的JVM,对其堆的使用情况进行实时的命令行的统计.
jstat -gcutil 20538 1000 100
jhat (Java Heap Analyse Tool)
用来分析java堆的命令(依赖jmap导出的bin文件),可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等
|
|
实战
问题服务情况
该进程的端口存活,但无法对外提供服务,该服务有定时任务、rmi接口,但整体压力不大,不应出现这种情况;
排查
- 该实例jvm内存参数配置如下(Xss为每个thread的内存占用,ps:太小了点)
|
|
- 查看实时gc情况
old区使用率一直是100%,fgc平均每秒两到三次,明细异常,且fgc之后无效果;
|
|
- 查看heap内存情况
显示的old区使用情况,
99.99994039535522% used
|
|
- dump jvm内存使用bin文件,以便后续分析
|
|
- 统计每个class的实例数量、内存占用、排名情况
|
|
可疑点
- old区满了之后,fgc无法释放,怀疑可能有
内存泄漏
情况; - jvm heap old区应占整个heap区的5/8,young区占3/8,但当前old区:young区为1:1,都为64M,不合理;
- heap整体内存太小,不够用;
尝试解决
修改进程的jvm参数配置
增加heap内存配置,不适用young的newRatio比例配置,使用设置固定数值,young区设定为128m,则old为384m,使得old区的比例基本为(5/8)*heap;
|
|
- 重启服务之后,查看gc情况
|
|
- 查看heap整体内存使用情况
|
|
结论
参数调整之后,fgc和ygc次数正常,服务正常;
但也不能认为就此就解决问题了,很可能是把参数调大了,暂时放缓了问题的出现,还需要多观察几天看下;
在观察的同时,需要根据上面第4步dump出来的当时jvm的内存使用情况的bin文件,分析有没有内存泄漏的情况;