Java 线上问题排查

Posted by sincosmos on July 4, 2020

JAVA 程序 CPU 使用率过高

一般地,Java 应用程序 CPU 使用率过高的原因有以下几种。

  1. 程序是计算密集型,例如正则表达式回溯,序列化和反序列化操作
  2. 程序发生死循环
  3. 程序频繁发生 Full GC
  4. 程序有较多阻塞性操作竞争锁,线程状态在 Blocked 和 Running 之间频繁切换 什么会导致Java应用程序的CPU使用率飙升?

原因排查

  1. 首先找到 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 实现。