模擬問題代碼
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)
,也就是那句輸出語句。