運行時優化
方法內聯
> 方法內聯,是指 **JVM在運行時將調用次數達到一定閾值的方法調用替換為方法體本身** ,從而消除調用成本,并為接下來進一步的代碼性能優化提供基礎,是JVM的一個重要優化手段之一。
>
> **注:**
>
> * **C++的inline屬于編譯后內聯,但是java是運行時內聯**
簡單通俗的講就是把方法內部調用的其它方法的邏輯,嵌入到自身的方法中去,變成自身的一部分,之后不再調用該方法,從而節省調用函數帶來的額外開支。
為什么會出現方法內聯呢?
之所以出現方法內聯是因為(方法調用)函數調用除了執行自身邏輯的開銷外,還有一些不為人知的額外開銷。 **這部分額外的開銷主要來自方法棧幀的生成、參數字段的壓入、棧幀的彈出、還有指令執行地址的跳轉** 。比如有下面這樣代碼:
```java
public static void function_A(int a, int b){
//do something
function_B(a,b);
}
public static void function_B(int c, int d){
//do something
}
public static void main(String[] args){
function_A(1,2);
}
```
則代碼的執行過程如下:
所以如果java中方法調用嵌套過多或者方法過多,這種額外的開銷就越多。
試想一下想get/set這種方法調用:
```java
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
```
**很可能自身執行邏輯的開銷還比不上為了調用這個方法的額外開鎖。如果類似的方法被頻繁的調用,則真正相對執行效率就會很低,雖然這類方法的執行時間很短。這也是為什么jvm會在熱點代碼中執行方法內聯的原因,這樣的話就可以省去調用調用函數帶來的額外開支。**
**這里舉個內聯的可能形式:**
```java
public int add(int a, int b , int c, int d){
return add(a, b) + add(c, d);
}
public int add(int a, int b){
return a + b;
}
```
**內聯之后:**
```java
public int add(int a, int b , int c, int d){
return a + b + c + d;
}
```
內聯條件
一個方法如果滿足以下條件就很可能被jvm內聯。
* 熱點代碼。
如果一個方法的執行頻率很高就表示優化的潛在價值就越大。那代碼執行多少次才能確定為熱點代碼?這是根據編譯器的編譯模式來決定的。如果是客戶端編譯模式則次數是1500,服務端編譯模式是10000。次