1.使用top命令查看内存使用最高的应用
使用大写M可按照内存使用排序,大写P可按cpu使用排序;
可以看到第一个java应用占用的cpu和内存明显高于其他几个;
2.定位线程问题
使用top查看第一个线程19503的线程情况
命令:top -Hp 19503
可以看到19503 这个pid应用产生了很多的线程;
3.查看内存使用的堆栈信息
使用jstack命令查看
将pid为19503 的应用打印到日志中
[root@localhost ~]# jstack -l 19503 > jstack_19503.log
4.查看内存堆栈信息
[root@localhost ~]# more jstack_19503.log
发现大量线程状态为WAITING的
parking to wait for <0x00000000e7e54130>
存在大量线程等待被唤醒,占用大量内存。
当然,其中原因可能不止这个,也可能发生死锁等情况,可以根据具体情况分析自己的代码,再根据实际情况优化修改;
补充:这里说一下使用jstack命令时遇到的异常情况:
1.登录用户和应用所属用户不一致:
19503: well-known file /tmp/.java_pid19503 is not secure: file's group should be the current group (which is 1000) but the group is 0
这个可能是由于应用的所属用户和当前用户不一致引起的,切换为应用所属用户即可
可以通过这个命令查看所有java应用的信息:
ps -ef | grep java
2.jstack无法连接jvm
19503: Unable to open socket file: target process not responding or HotSpot VM not loaded
看到网上很多解答说是因为:这个java进程的pid文件删除了。
由于linux操作系统为了防止/tmp目录文件过多,有个删除管理机制:tmpwatch;
系统每天会用tmpwatch命令检查并删除 /tmp 下超过240小时未访问过的文件和目录。
具体解决办法:https://blog.51cto.com/zhangshaoxiong/1310166
但是感觉修改较为复杂,且需要修改到系统文件,所以我这边使用了一个临时方法,在启动jar包时加一个命令指定一个临时文件夹即可:
java -Djava.io.tmpdir=/tmp/tmpdir -Dfile.encoding=utf-8 -Xmx512m -jar test.jar --spring.profiles.active=test
其中的-Djava.io.tmpdir=/tmp/tmpdir
命令增加的指定命令,/tmp/tmpdir
为指定文件夹位置。