1. 程式人生 > >找出java程式碼中佔用cpu過多問題

找出java程式碼中佔用cpu過多問題

當有java程序佔用過多CPU時,可能是邏輯出現的問題。如何排查問題所在呢?

1. 使用top工具列出所有程序,shitf + p 列出CPU佔用率較高程序

2. 找到問題程序號,使用top -H -p pid列出程序的所有執行緒

3. 然後shift + p 按照CPU使用率排序

4. 找出問題程序號,打印出其16進位制值,printf "%x", ppid,比如是:76a3

5. jstack pid > t.dat 記錄執行緒堆疊,vi 開啟找到76a3的執行緒號,結合原始碼定位問題

下面使用一個死迴圈的例子進行講解:

public class Main {
    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread(new T1());
        t1.setName("tone");
        Thread t2 = new Thread(new T2());
        t2.setName("ttwo");
        
        t1.start();
        t2.start();
    }
    
    
    public static class T1 implements Runnable {
        public void run() {
            int a = 0;
            while (true) {
                a++;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    public static class T2 implements Runnable {
        public void run() {
            long a = 0L;
            while (true) {
                a++;
            }
        }
    }
}

上面的程式碼啟動兩個執行緒,執行緒T1會佔用少量CPU,執行緒T2會佔滿一個CPU。

首先我們通過top列出程序,按照cpu使用率排序(shift + p)


可以看出出問題的程序號是30358

然後使用 top -H -p 30358 得到如下結果,然後使用shitf + p按照cpu使用率排序


這裡可以看到執行緒為30371佔用太多CPU,此執行緒有問題

接下來使用jstack 30358 > t.dat 記錄執行緒堆疊

使用python打印出出30371的16進位制值 (print("0x" % 30371結果為76a3

線上程堆疊中找到76a3程序,然後仔細檢視堆疊資訊


這裡可以看到ttwo執行緒名,執行到了Main的31行,此時我們在去原始碼中仔細檢視附近的邏輯,問題一目瞭然