JAVA 程序 CPU 使用率过高
一般地,Java 应用程序 CPU 使用率过高的原因有以下几种。
- 程序是计算密集型,例如正则表达式回溯,序列化和反序列化操作
- 程序发生死循环
- 程序频繁发生 Full GC
- 程序有较多阻塞性操作竞争锁,线程状态在 Blocked 和 Running 之间频繁切换 什么会导致Java应用程序的CPU使用率飙升?
原因排查
- 首先找到 CPU 使用率过高的 java 进程号及线程号
# 设定刷新时间 1s,shift + p 按照进程 CPU 使用率排序(shift + m 按照内存使用量排序),找到 CPU 占用较高的进程号
$ top -d 1
# 获得相应进程下的所有线程,找到 CPU 占用较高的线程号
$ top -Hp pid
# or
$ ps -mp pid -o THREAD,tid,time
# 将 tid 转换为 16 进制
$ printf '%x\n' tid
# 使用 jstack 获取线程信息,并显示下文
$ jstack pid | grep tid_hex -A 10
上述找到线程 stack 的过程可以使用一个脚本自动实现。show-busy-java-threads
JVM 监控
btrace 动态跟踪 Java 运行时程序
jmap
jmap 命令用来查看 java 进程中内存使用信息,对内存泄漏、内存不足等问题的排查有很大帮助。
# 按照占用空间的大小,显示程序中类列表
$ jmap -histo:live pid
# 查看堆内存的概要信息
$ jmap -heap pid
# 导出堆内存快照
$ jmap -dump:format=b,file=./heap.hprof pid
jstat
jstat 对 Java 应用程序的资源和性能进行实时监控,包括对堆大小和垃圾回收状况等。与 jmap 相比,jstat 更倾向于输出累积的信息与打印 GC 等的统计信息等,例如 GC 次数,已用内存占比等。
jstat -gcutil pid 5000 10
jstack
我们在排查 java 程序 CPU 占用过高的时候,利用了 jstack 工具,该命令用于查询给定进程/线程的栈快照信息,从而可以看到 Java 进程/线程的执行状态,可以据此分析线程的等待、死锁等问题。
jinfo
输出并修改运行时 Java 进程的环境变量和虚拟机参数。
jps
查找 Java 进程,可以使用 ps 命令 grep 实现。