最近因为太忙,时间不够,导致长时间没写笔录,没有好好去总结自己,很不应该,要调整回来。
这一次就记录一下,在生产中真实的 JVM 内存调优(内存分析)经历吧。
晚上领导电话过来说:服务怎么打不开了,是不是挂了?
(第一时间查看日志?不不不)
我:
在看日志的路上,突然发现当前服务器的 cpu 和 内存 全部跑满了。原来是因为CPU爆满,导致服务器呈现卡顿乃至是死机无法连接等状况。
OK啊,问题解决,买台更好的服务器就行了(哈哈)
一般 Java 应用 cpu 过高基本上是因为
但是 Java 项目很大,功能很多,如何知道是哪行代码出现问题呢?这时候就需要内存分析了
在Linux终端输入:top -d 1
当前命令可以查看各个进程占用 cpu 情况,一般排名第一位肯定是 Java 进程,当然也可能存在多个 Java 进程

观察 top 消耗第一的资源是PID=12708
通过第一步知道消耗第一的进程,然后输入: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。占用最大,时间最长。
TID 为12723的线程利用 cpu 资源比较多,怎么能看到这个线程在干什么呢?
第一步:需要将12723 转换为16进制,便于在jvm堆栈中查找,命令:printf "%x\n" 12723 。
当前指令会打印 12723 对应的16进制,也就是:31b3

第二步:通过 jstack 命令来查看下当前内存状态
命令:jstack pid | grep 对应的16进制 -A 30
如:jstack 12708 | grep 31b3 -A 30(注意 下图pid和16进制不同)

这样就可以定位到是哪行代码出现问题,从而进行优化。
我的问题便是当前循环次数太大了,一直在运行,线程一直未被释放,然后下次请求很快又来了,从而又运行了一次循环代码,一直累加,导致CPU跑满。
问题排查结束,在运行 Java 程序时。
当然真正的 JVM 调优远比这要复杂高深,这次只是浅浅的接触了 JVM 内存、 jstack,但这次经历很有收获。
新年快乐,愿你我一直在前行!