生产环境出现CPU占用过高,请谈谈你的分析思路和定位
模拟问题代码
import java.util.Random; public class HighCPUDemo{ public static void main(String[] args) { while (true){ System.out.println(new Random(999999)); } } }
当编译运行上面代码则会循环打印,对CPU占用较高
下面演示全部过程,首先运行代码
[root@izuf67vu7do989lgqvknozz ~]# javac HighCPUDemo.java [root@izuf67vu7do989lgqvknozz ~]# java HighCPUDemo
此时,代码运行起来,后台在循环输出随机数,CPU占用过高
问题分析:结合Linux和jdk一块分析
代码运行起来后可用top查看占用CPU最高的进程或者jps命令查看是哪些运行的java进程
1、top命令-找到CPU占比最高的进程
找到占用最高的进程是java进程,进程id:11849
2、ps -ef或者jps定位
得知是一个怎么样的后台程序给我们惹事
[root@izuf67vu7do989lgqvknozz ~]# jps -l 11861 sun.tools.jps.Jps 11849 HighCPUDemo [root@izuf67vu7do989lgqvknozz ~]# ps -ef|grep java|grep -v grep root 11849 11636 14 10:02 pts/0 00:00:13 java HighCPUDemo
以上两种方式都可以查看java进程,找到了java进程,接下来就要定位到具体的线程或者代码
公式:
ps -mp 进程 -o THREAD, tid, time
参数解释
-m 显示所有的线程
-p pid 进程使用cpu的时间
-o 该参数后是用户自定义格式
3、定位具体线程
输入公式,显示出下面的结果,找到占用CPU最高的那个线程,找出线程id-->TID--->11850
[root@izuf67vu7do989lgqvknozz ~]# ps -mp 11849 -o THREAD,tid,time USER %CPU PRI SCNT WCHAN USER SYSTEM TID TIME root 13.8 - - - - - - 00:00:24 root 0.0 19 - futex_ - - 11849 00:00:00 root 13.5 19 - n_tty_ - - 11850 00:00:23 root 0.0 19 - futex_ - - 11851 00:00:00 root 0.0 19 - futex_ - - 11852 00:00:00 root 0.0 19 - futex_ - - 11853 00:00:00 root 0.0 19 - futex_ - - 11854 00:00:00 root 0.0 19 - futex_ - - 11855 00:00:00 root 0.0 19 - futex_ - - 11856 00:00:00 root 0.0 19 - futex_ - - 11857 00:00:00 root 0.0 19 - futex_ - - 11858 00:00:00
4、将需要的线程id转换为16进制格式(英文小写格式)
公式:
printf "%x\n"有问题的线程ID
下面是运算结果
[root@izuf67vu7do989lgqvknozz ~]# printf "%x\n" 11850 2e4a
即11850的16进制是2e4a
5、找出具体的问题代码
公式
jstack 进程id | grep tid(16进制线程id小写英文)-A60
显示出有问题的代码
[root@izuf67vu7do989lgqvknozz ~]# jstack 11849 |grep 2e4a -A60 "main" #1 prio=5 os_prio=0 tid=0x00007f8968008800 nid=0x2e4a runnable [0x00007f8970626000] 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 <0x00000000ecd6b900> (a java.io.BufferedOutputStream) at java.io.PrintStream.write(PrintStream.java:482) - locked <0x00000000ecd63d70> (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 <0x00000000ecd63d28> (a java.io.OutputStreamWriter) at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185) at java.io.PrintStream.newLine(PrintStream.java:546) - eliminated <0x00000000ecd63d70> (a java.io.PrintStream) at java.io.PrintStream.println(PrintStream.java:824) - locked <0x00000000ecd63d70> (a java.io.PrintStream) at HighCPUDemo.main(HighCPUDemo.java:7) "VM Thread" os_prio=0 tid=0x00007f896806d000 nid=0x2e4b runnable "VM Periodic Task Thread" os_prio=0 tid=0x00007f89680b5800 nid=0x2e52 waiting on condition JNI global references: 9
从结果上显示,问题代码出现在at HighCPUDemo.main(HighCPUDemo.java:7)
,也就是那句输出语句。