Java程序 内存分析

2023-10-21 12:39:52 浏览数 (1)

最近因为太忙,时间不够,导致长时间没写笔录,没有好好去总结自己,很不应该,要调整回来。

这一次就记录一下,在生产中真实的 JVM 内存调优(内存分析)经历吧。

一、原由

晚上领导电话过来说:服务怎么打不开了,是不是挂了?

(第一时间查看日志?不不不)

我:

在看日志的路上,突然发现当前服务器的 cpu内存 全部跑满了。原来是因为CPU爆满,导致服务器呈现卡顿乃至是死机无法连接等状况。

OK啊,问题解决,买台更好的服务器就行了(哈哈)

二、问题排查

一般 Java 应用 cpu 过高基本上是因为

  1. 程序计算比较密集
  2. 程序死循环
  3. 程序逻请求堵塞
  4. 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,但这次经历很有收获。

新年快乐,愿你我一直在前行!

0 人点赞