项目里JVM实战

不知道大家知不道自己项目中的JVM相关参数,比如设置的堆的内存是多少,新生代内存多少,什么垃圾回收器,GC频率等等,所以这篇文章从实际出发探索项目中的JVM参数。

1.准备工作
内存分析工具准备
有很多内存分析工具,如IBM的HeapAnalyzer,eclipse的MAT
这里使用eclipse的MAT
官方下载地址

常用命令:
top  查看监控整体信息
jps  可以查看部署的Java Pid
jinfo 可以查看jvm相关参数
jstat 可以查看gc相关信息,比如gc次数,新生代,老年代占比等等
jmap  用于查看堆信息,当然也可以导出dump文件

这些都是命令行工具,当然也有可视化工具
jconsole,jvisualvm

2.直接开始
由于我们生产环境不允许操作,所以退而求次使用测试环境来操作。
首先我是发现我们young gc比较频繁,大概1分多钟一次;full gc次数比较低。触发young gc的条件就是eden区满了,所以想知道为啥eden区这么快就满了。可以看到YGC次数已经1061次了
在这里插入图片描述
参数含义在下边再解释

①使用top或者jps命令找到Java进程的Pid
top -b 找到java pid 35
项目里JVM实战_第1张图片
jps 35
在这里插入图片描述
②使用jinfo查看我们的jvm信息,可以看到新生代,老年代,垃圾回收器类型等等
jinfo -flags 35
在这里插入图片描述

我们一般用下列参数来初始化jvm参数
-Xms 最小堆内存
-Xmx 最大堆内存
-Xmn 新生代内存=-XX:newSize = -XX:MaxnewSize = -Xmn.也就是说-Xmn会同时设置前面2个参数
-XX:+UseXXGC 表示使用哪种GC
-XX:PermSize 设置永久代最小空间大小。
-XX:MaxPermSize 设置永久代最大空间大小。
-Xss 设置每个线程的堆栈大小。
-XX:NewRatio=n:设置年轻代和年老代的比值。如:3,表示年轻代与年老代比值为13,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=32,一个Survivor区占整个年轻代的1/5

③使用jstat查看gc信息
jstat -gcutil 35 以百分比展示堆信息
在这里插入图片描述

各参数含义:
S0   survivor区
S1   survivor区
E    eden区
O    老年代区
M    jdk1.8是元空间 1.7是P 永久代
CCS  压缩空间
YGC  young gc 次数
YGCT young gc 耗时
FGC  full gc 次数
FGCT full gc 耗时
GCT  gc总耗时

可以参考这个
④使用jmap导出堆栈信息
jmap -dump:format=b,file=heap.hprof 35
在这里插入图片描述
⑤打开刚刚下载的MAT工具,左上角file将jmap导出的heap.hprof文件导入MAT工具

这里我们主要关注 leak suspects,很贴心,已经把可能发生内存泄露的地方给我们找出来了,点进去看看。
项目里JVM实战_第2张图片
可以看到上面26.47%的内存都是我打码的对象,这个类是全链路的监控的类,用于产生拦截对象,可以猜测一下,全链路我们是用Java探针接入的,类似于代理,在我们请求前后使用拦截器拦截收集我们的请求信息,然后请求完了,就可以回收拦截器对象了,所以可以看到我们eden区由于创建拦截器对象很快就慢了,然后又被ygc回收掉。
当然实际排查过程中没有这么简单,通常隐藏层级很深,这是就要用到其他特性了。

比如Dominator Tree: 可以看到对象所占内存占比,我们就可以优先排查那些大对象
项目里JVM实战_第3张图片
可以看到上图的Shallow Heap 和 Retained Heap
Shallow Heap 和 Retained Heap的含义
Shallow Heap:是对象本身占据的内存的大小,不包含其引用的对象
Retained Heap:当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C,C就是间接引用) ,并且排除被GC Roots直接或者间接引用的对象
具体区别可以参考这篇文章:
添加链接描述
而这个对象被gc回收释放的内存就是Retained Heap

然后点击对象进行 点击list objetcs incoming 和 outgoing references分析
incoming references:引用该对象的对象
outgoing references:该对象引用的对象
比如A,B引用C,C引用D,E
站在C的角度,AB就是C的incoming references,DE是C的outgoing references

项目里JVM实战_第4张图片
我们这是查看的outgoing references,也就是该对象引用的对象,可以看到有一个array,里面全是拦截器对象,可以印证我们刚刚上面说的
项目里JVM实战_第5张图片
大体流程就是这样,大家不懂多搜,多尝试。

你可能感兴趣的:(Java,内存泄漏)