最近因为太忙,时间不够,导致长时间没写笔录,没有好好去总结自己,很不应该,要调整回来。
这一次就记录一下,在生产中真实的 JVM
内存调优(内存分析)经历吧。
一、原由
晚上领导电话过来说:服务怎么打不开了,是不是挂了?
(第一时间查看日志?不不不)
我:
在看日志的路上,突然发现当前服务器的 cpu
和 内存
全部跑满了。原来是因为CPU爆满,导致服务器呈现卡顿乃至是死机无法连接等状况。
OK啊,问题解决,买台更好的服务器就行了(哈哈)
二、问题排查
一般 Java
应用 cpu
过高基本上是因为
- 程序计算比较密集
- 程序死循环
- 程序逻请求堵塞
- IO读写太高
但是 Java
项目很大,功能很多,如何知道是哪行代码出现问题呢?这时候就需要内存分析
了
1. 查看各个进程占用 cpu 情况
在Linux终端输入:top -d 1
当前命令可以查看各个进程占用 cpu
情况,一般排名第一位肯定是 Java
进程,当然也可能存在多个 Java
进程
观察 top
消耗第一的资源是PID=12708
2. 查看进程的哪个线程占用 cpu 比较高
通过第一步知道消耗第一的进程,然后输入:ps -mp pid -o THREAD,tid,time
其中 pid
修改为 CPU
消耗第一的进程的pid
,也就是:ps -mp 12708 -o THREAD,tid,time
通过以上线程 CPU
切片,耗时在pid=12708,Tid=12723,耗时12分22秒,使用5.4%CPU。占用最大,时间最长。
3. 查看对应线程在运行什么任务
TID
为12723的线程利用 cpu
资源比较多,怎么能看到这个线程在干什么呢?
第一步:需要将12723 转换为16进制,便于在jvm堆栈中查找,命令:printf "%xn" 12723
。
当前指令会打印 12723
对应的16进制,也就是:31b3
第二步:通过 jstack
命令来查看下当前内存状态
命令:jstack pid | grep 对应的16进制 -A 30
如:jstack 12708 | grep 31b3 -A 30
(注意 下图pid和16进制不同)
这样就可以定位到是哪行代码出现问题,从而进行优化。
我的问题便是当前循环次数太大了,一直在运行,线程一直未被释放,然后下次请求很快又来了,从而又运行了一次循环代码,一直累加,导致CPU
跑满。
问题排查结束,在运行 Java
程序时。
三、结尾
当然真正的 JVM
调优远比这要复杂高深,这次只是浅浅的接触了 JVM
内存、 jstack
,但这次经历很有收获。
新年快乐,愿你我一直在前行!