生产环境出现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),也就是那句输出语句。

以上就是具体的案例分析,

posted @ 2019-10-12 10:36  大宇007  阅读(913)  评论(1编辑  收藏  举报