JVM 方法內聯

2021-10-08 23:26:51 字數 2625 閱讀 4145

jvm學習記錄

方法內聯(inlining,對效能的提公升很大):方法內聯可以減少方法呼叫,從而減少方法棧的建立。

簡單點說:就是把被呼叫方函式**"複製"到呼叫方函式中,減少因函式呼叫開銷的技術。

相信大家都知道迴圈的速度比遞迴快很多,就是這個原因,另外方法內聯後,還使得一些jit更深入的優化變成可能。jvm可以通過兩個啟動引數來控制位元組碼大小為多少的方法可以被內聯:

-xx:maxinlinesize:能被內聯的方法的最大位元組碼大小,預設值為35byte,這種方法不需要頻繁的呼叫。比如:一般pojo類中的getter和setter方法,它們不是那種呼叫頻率特別高的方法,但是它們的位元組碼大小非常短,這種方法會在執行後被內聯。

-xx:freqinlinesize:呼叫很頻繁的方法能被內聯的最大位元組碼大小,這個大小可以比maxinlinesize大,預設值為325byte(和平台有關,我的機器是64位windows)。

函式的呼叫過程首先會有乙個執行棧,儲存它們的區域性變數、動態鏈結、方法出口等。

當乙個方法被呼叫,乙個新的棧幀會被載入到棧頂,分配的本地變數和引數會儲存在這個棧幀中。

跳轉到目標方法**執行

方法返回的時候,彈棧並銷毀

返回原來的位址執行

注:這就是通常說的壓棧和出棧過程,因此,函式呼叫需要有一定的時間開銷和空間開銷,當乙個方法體不大,但又頻繁被呼叫時,這個時間和空間開銷會相對變得很大,變得非常不划算,同時降低了程式的效能。根據二八原則,80%的效能消耗其實是發生在20%的**上,對熱點**的針對性優化可以提公升整體系統的效能

方法內聯的條件jvm會自動識別熱點方法,並對它們使用方法內聯進行優化,那優化的條件是什麼呢?

通常這個值由-xx:compilethreshold引數進行設定:

使用client編譯器時,預設為1500;

使用server編譯器時,預設為10000;

當某個方法被連續呼叫這麼多次後,就相當於是乙個熱點方法,就可能被jvm進行方法內聯優化,注意是可能。

為什麼呢?

其中有個比較常見的原因就是這個方法體太大了,分為兩種情況:

如果方法是經常執行的,預設情況下,方法大小小於325位元組的都會進行內聯(可以通過-xx:maxfreqinlinesize=n來設定這個大小)

如果方法不是經常執行的,預設情況下,方法大小小於35位元組才會進行內聯(可以通過-xx:maxinlinesize=n來設定這個大小)

效果演示來乙個簡單的測試**

public

class

listtest

}public

intprintstr()

public

intp

(int i,

int s)

}

新增三個jvm引數:(-xx:+printcompilation -xx:+unlockdiagnosticvmoptions -xx:+printinlining)

接下來分別演示一下沒有出現方法內聯優化與出現優化的情況,看控制台列印出的日誌資訊

注:inline (hot)表示當前呼叫已被內聯

實驗測試過程中,也在5000以後有時候也出現了方法內聯優化,而5000以內基本不會出現,雖然p()方法被呼叫了10000+,但是也不一定會出現內聯優化。

方法內聯可以消除呼叫本身帶來的開銷,還可以進一步出發更多的優化。

內聯越多,生成**的執行效率越高。 然而對於即時編譯器來說,內聯越多,編譯時間也就越長,而程式達到峰值的時刻也將被推遲。也會導致生成的機器碼越長。

內聯規則:

雖然jit號稱可以針對**全域性的運**況而優化,但是jit對乙個方法內聯之後,還可能因為方法被繼承,導致需要型別檢查而沒有達到效能的效果。

想要對熱點的方法使用上內聯的優化方法,最好盡量使用final、private、static這些修飾符修飾方法,避免方法因為繼承,導致需要額外的型別檢查,而出現效果不好的情況。

結論針對熱點方法,想要通過jit內聯優化來提公升效能的建議

更小的方法體,jvm總是偏好更小的方法。

盡量使用final、private、static修飾符

使用+printinlining引數校驗效果(這兩個要一起使用 【-xx:+unlockdiagnosticvmoptions -xx:+printinlining】)

JVM方法分派

方法靜態分派演示 方法靜態分派演示 created by tiantao on 15 2 9.public class staticdispatch static class man extends human static class woman extends human public void...

JVM方法呼叫指令

終於把inside jvm這本看完了,好久沒這麼細緻的看一本書了。好多人都寫了文章討論jvm如何實現多型的,我只是簡單做個筆記。類的位元組碼結構有個常量池,其中就存放了這個類中呼叫的方法的符號引用,這些符號引用實際上是放在一些特殊型別 constant nameandtype info 的常量池入口...

JVM基礎 方法區

元空間記憶體溢位 jvm的方法區是被所有執行緒共享的,是在虛擬機器啟動時建立。方法區存放每個類的構造資訊,比如型別資訊 比如完全限定名 父類完全限定名 訪問修飾符 執行時常量池 靜態變數 即時編譯器jit編譯後的 快取 字段資訊 構造方法 方法 載入當前類的類的載入器等 jvm官方規範對方法區的定義...