Java程序CPU占用过高(100%)解决思路和解决方案
1. 线上诊断工具Arthas
详情见之前的BLGO: Web应用线上诊断工具-Arthas
2. 采用JDK自带的jstack进行排查
2.1 使用top查看进程内存占用情况
[root@honor ~]# top
2.2 使用PS来分析进程和线程的占用情况
- 通过这种方式来找到线程占用高的线程id
[root@honor ~]# ps H -eo pid,tid,%cpu
#grep 后面进行进程id
[root@honor ~]# ps H -eo pid,tid,%cpu|grep 14937
- 我们可以看到进程为20059的线程CPU占用偏高
2.3 采用jstack 来进行虚拟机栈的区分
- 使用jstack来查看 jstack PID
[root@honor ~]# jstack 20058
- 执行过后我们会得到一下内容
2022-04-20 19:42:27
Full thread dump OpenJDK 64-Bit Server VM (25.242-b08 mixed mode):
"Attach Listener" #9 daemon prio=9 os_prio=0 tid=0x00007f9c64001000 nid=0x6c49 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Service Thread" #8 daemon prio=9 os_prio=0 tid=0x00007f9cac12c000 nid=0x4e67 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C1 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f9cac121000 nid=0x4e66 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f9cac11f000 nid=0x4e65 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f9cac110000 nid=0x4e64 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f9cac10d800 nid=0x4e63 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f9cac0e3800 nid=0x4e62 in Object.wait() [0x00007f9c982c5000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000721588668> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x0000000721588668> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f9cac0df000 nid=0x4e61 in Object.wait() [0x00007f9c983c6000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000721590188> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x0000000721590188> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"main" #1 prio=5 os_prio=0 tid=0x00007f9cac04b800 nid=0x4e5b runnable [0x00007f9cb319d000]
java.lang.Thread.State: RUNNABLE
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:326)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
- locked <0x000000072158dd90> (a java.io.BufferedOutputStream)
at java.io.PrintStream.write(PrintStream.java:482)
- locked <0x0000000721584c20> (a java.io.PrintStream)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
- locked <0x0000000721584bd8> (a java.io.OutputStreamWriter)
at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
at java.io.PrintStream.newLine(PrintStream.java:546)
- eliminated <0x0000000721584c20> (a java.io.PrintStream)
at java.io.PrintStream.println(PrintStream.java:807)
- locked <0x0000000721584c20> (a java.io.PrintStream)
at Hello.main(Hello.java:6)
"VM Thread" os_prio=0 tid=0x00007f9cac0d5000 nid=0x4e60 runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f9cac05e000 nid=0x4e5c runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f9cac05f800 nid=0x4e5d runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f9cac061800 nid=0x4e5e runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f9cac063800 nid=0x4e5f runnable
"VM Periodic Task Thread" os_prio=0 tid=0x00007f9cac12e800 nid=0x4e68 waiting on condition
JNI global references: 5
-
注意找关键点 nid(nid 为16进制 线程为10进制)
-
得到 4e5b 然后去查找该tid 可以得到是哪个占用过高 atHello.main(Hello.java:6)
2.4 总结
根据jstack分析得知 当前线程占用过高是因为死循环产生的
3. 分析dump或hprof文件
3.1 生成dump或hprof文件
## 20058为PID
[root@honor ~]# jmap -dump:file=javaDump.hprof,format=b 20058
[root@honor ~]# jmap -dump:file=javaDump.dump,format=b 20058
3.2 使用JDK自带的jvisualvm来分析dump文件
- 目录:C:\Program Files\Java\jdk1.8.0_66\bin
- 此处dump和hprof文件操作步骤相同不一一描述。
3.2.1 导入dump文件
3.2.2 查看hprof文件
- 概要:主要显示基本信息,环境,系统属性及可选择的占用最大的对象
- 类:可分析使用最多的类及其详细信息
- 监视:CPU、内存、类、线程的实时情况
- 线程:可查看线程的使用情况
3.2.2 使用远程来查看
本文作者:张三Blog
本文链接:https://www.cnblogs.com/zhangsan-plus/p/16503247.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步