天天看點

JVM系列之:通過一個例子分析JIT的彙編代碼簡介一個簡單的例子使用jitWatch進行分析分析位元組碼分析彙編代碼總結

簡介

我們知道JIT會在JVM運作過程中,對熱點代碼進行優化,傳說自然是傳說,今天我們通過一個簡單的例子來具體分析一下JIT到底是怎麼進行優化的。

一個簡單的例子

說幹就幹,我們先準備一個非常簡單的例子:

public class AddTest {
    static int a = 1;
    static int b = 2;
    static int c = 3;

    public static void main(String[] args) {
        for (int i = 0; i < 100000; i++) {
            add();
        }
    }

    private static void add() {
        a = b + 1;
        b = c + 2;
        c = a + 3;
    }
}
           

這個例子中我們定義了三個類變量,然後通過一個add方法對其中的變量進行累加。

然後在main方法中對add方法調用10000次。調用這麼多次,主要是為了保證add成為熱點代碼,進而使用JIT進行編譯。

使用jitWatch進行分析

之前提到了JIT分析的神器jitWatch,今天我們來使用jitWatch來分析上面的代碼。

從jitWatch的github中下載下傳源碼,運作mvn exec:java即可開啟jitWatch之旅。

打開sandbox,選擇我們編寫的類檔案。點選運作即可。

然後我們到了下面熟悉的界面:

JVM系列之:通過一個例子分析JIT的彙編代碼簡介一個簡單的例子使用jitWatch進行分析分析位元組碼分析彙編代碼總結

界面分為三部分,左邊是源代碼,中間是位元組碼,最右邊是JIT編譯的彙編代碼。

分析位元組碼

我們分析下add方法生成的位元組碼:

0: getstatic       #13  // Field b:I
 3: iconst_1        
 4: iadd            
 5: putstatic       #17  // Field a:I
 8: getstatic       #20  // Field c:I
11: iconst_2        
12: iadd            
13: putstatic       #13  // Field b:I
16: getstatic       #17  // Field a:I
19: iconst_3        
20: iadd            
21: putstatic       #20  // Field c:I
24: return          
           

我們可以看到位元組碼和java源代碼是一一對應的。

比如add方法的第一行:

a = b + 1;
           

相應的位元組碼是這樣的:

0: getstatic       #13  // Field b:I
 3: iconst_1        
 4: iadd            
 5: putstatic       #17  // Field a:I
           

首先通過getstatic拿到字段b的值。然後調用iconst_1,将1加載。接着調用iadd把1和b相加。最後将生成的值使用putstatic指派給a。

位元組碼和源代碼一一對應,完全沒有問題。

分析彙編代碼

那麼JIT生成的彙編代碼是不是也和java代碼一緻呢?我們再來看一下生成的彙編代碼。

JVM系列之:通過一個例子分析JIT的彙編代碼簡介一個簡單的例子使用jitWatch進行分析分析位元組碼分析彙編代碼總結

從圖檔我們可以看出,生成的彙編代碼可以分為方法初始化,代碼邏輯區,多線程同步,位址和cache line對齊,異常處理,返優化等幾個部分。

這裡我們主要關注一下代碼邏輯區:

JVM系列之:通過一個例子分析JIT的彙編代碼簡介一個簡單的例子使用jitWatch進行分析分析位元組碼分析彙編代碼總結

從圖上我做的标記可以看出,彙編中執行的邏輯是 b=c+2, a =b+1和c=b+4。

不光執行順序發送了變化(重排序),執行邏輯也進行了優化。

大家可能注意到彙編語言中有這樣幾個不太明白的代碼:

0x78(%r10)
0x74(%r10)
0x70(%r10)
           

通過第二行的注解,我們知道r10存儲的是AddTest這個對象,而0x70,0x74和0x78是AddTest中的偏移量,用來定位類變量a,b,c。

總結

從上面的例子可以知道,JIT會對代碼進行優化,是以最好的辦法是不要自己在java代碼中做一些你認為是優化的優化,因為這樣可能讓JIT在優化的時候變得困惑。進而限制了代碼優化的力度。

最後,JIT是一個非常強大的工具。希望大家能夠喜歡。

小編為大家整理了很多JVM的視訊資料,大家可以添加V:mm7718mm,自行擷取。