背景介绍:
之前开发xxl-job的项目时,从来没有考虑过JVM调优的问题。以至于,积小成大,问题出现了,随着部署的项目越来越多,服务器内存的占用率越来越高。这也属于正常现象,可是原本在mule上运行时明明可以部署同样的项目,内存还绰绰有余,为什么改成xxl-job就不行了呢?
经过观察发现项目的占用内存在不断的增长,但cpu利用率却很低。如下图所示:
重启后可以降低内存占用,但随着运行时间变长,内存占用率也在持续增加,而CPU利用率却很低。
小白分析:
Tip: 因为没有关注过这一块儿,所以也不知道从何下手,故分析的过程和结果只是个人理解~,以下用到的工具命令什么的都是现学的,简单了解一下吧。
起初:
同事告诉我服务器上的项目内存一直在不断的增长,让我看看什么原因。
我第一反应可能是代码里面我是不是写了什么流没关闭,什么for循环的,或者内存泄漏啥的,可这些咱也不懂啊。
然后走的弯路: 就~~~~~~~~~~~很长。
研究——–
中间:
工具Arthas(阿尔萨斯)
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
选择要查看的 java 进程:
jvm 相关
- dashboard – 当前系统的实时数据面板
- getstatic – 查看类的静态属性
- heapdump – dump java heap, 类似 jmap 命令的 heap dump 功能
- jvm – 查看当前 JVM 的信息
- logger – 查看和修改 logger
- mbean – 查看 Mbean 的信息
- memory – 查看 JVM 的内存信息
- ognl – 执行 ognl 表达式
- perfcounter – 查看当前 JVM 的 Perf Counter 信息
- sysenv – 查看 JVM 的环境变量
- sysprop – 查看和修改 JVM 的系统属性
- thread – 查看当前 JVM 的线程堆栈信息
- vmoption – 查看和修改 JVM 里诊断相关的 option
- vmtool – 从 jvm 里查询对象,执行 forceGc
看点:使用上面的工具分析,发现进程的大部分时间,内存实际占用率(used)并没有查出来的RES值那么高,排除内存溢出。(到这里还不知道RES值的计算方式)
RES = heap +nonheap + code_cache + metaspace + compressed_class_space
了解到这里,还是不知道原因。
继续研究,了解到了Xms和Xmx两个参数,再结合上面的数据,可以看出分配的内存并没有及时释放掉,到这里思路就明确了,开始考虑jvm垃圾回收类型。
常用命令分析:
- 根据进程号pid查看多少次内的GC记录
jstat -gc pid 3000 30
ps:3000是间隔时间,30是次数
- 根据pid查看JVM启动参数
jcmd pid VM.flags
经过查阅资料发现,可以将垃圾回收类型换成-XX:+UseG1GC
借助工具VisualVM分析一下-XX:+UseParallelGC和-XX:+UseG1GC
启动参数:-Xms10m -Xmx1024m -XX:+UseG1GC
启动参数:-Xms10m -Xmx1024m -XX:+UseParallelGC
总结:
可以看出UseG1GC内存占用率比较低。
ps:垃圾回收器类型,算法百度了解一下就可以,还有各项参数也可以了解一下。
Tip:
- 内存是否归还系统,取决于Xms和Xmx两个参数是否相等。(相等可以避免内存抖动现象,不相等可以释放内存)
- 内存什么时候归还,取决于垃圾回收器类型。
- Xms一般取值系统内存的1/64,Xmx一般取值系统内存的1/4
- 堆内内存实际使用内存(used)低于分配内存(total)的30%会释放内存,重新分配到Xms的值,剩余分配内存低于40%会提前申请内存,直到Xmx的值,超过就会内存溢出。
更换垃圾回收器类型后的数据
内存打下来了,开心~
扩展命令:
查询堆内存前20的占用对象
jmap -histo:live pid | head -20
评论前必须登录!
注册