JVM中的熱點代碼檢測機制主要有三種,分別為基於采樣的熱點探測,基於計數器的熱點探測和基於蹤跡的熱點探測。
基於采樣的熱點探測
采用這種方法的虛擬機會周期性地檢查各個線程的棧頂,如果發現某個方法經常出現在棧頂,這個方法就是熱點方法。
優點:這種方法實現起來較為簡單,可以很容易的獲取方法調用的關系。
缺點:由於有線程阻塞或別的因素影響,無法精確的對熱點進行探測。
基於計數器的熱點探測
采用這種方法的虛擬機會為每個方法(甚至是代碼塊)建立並維護計數器,統計方法的執行次數,執行次數超過一定的閥值就會認為它是熱點方法,計數器可以分為兩類:
1.方法調用計數器:統計一段時間內方法被調用的次數,如果執行次數超過一定的閾值,就認為他是熱點方法。方法調用計數器統計的並不是方法被調用的絕對次數,而是一個相對的執行頻率,即一段時間內方法被調用的次數,當超過一定的時間限度,如果方法的調用次數仍然不足以讓它提交給即時編譯器,那這個方法的調用計數器就會被減少一半,這個過程被稱為【方法調用計數器熱度的衰減】,而這段時間就稱為【方法統計的半衰周期】,進行熱度衰減的動作在虛擬機進行垃圾收集時就順便進行了。
2.回邊計數器:主要是統計循環體內的代碼執行的次數,在字節碼遇到控制流后向后跳轉的指令被稱為回邊,建立回邊計數器也是為了觸發OSR(On-Stack Replacement,運行時替換棧幀技術)。因為沒有計數熱度衰減的過程,因此這個計數器統計的就是該方法執行循環的絕對次數,當計數器溢出的時候,它還會把方法計數器的值也調整到溢出的狀態,這樣下去在再次進入該方法的時候就會執行標准編譯過程。比如在空循環的情況下,照樣會執行對應的次數,但它是直接跳轉到自己,所以JIT編譯器去編譯這種代碼是沒有任何意義的。
優點:這種方式更加精確和嚴謹。
缺點:統計時需要為每個方法建立並維護計數器,而且不能獲取方法的調用關系,實現起來較為麻煩。
基於蹤跡(Trace)的熱點探測
采用這種方式的虛擬機是將一段頻繁執行的代碼作為一個編譯單元,並僅對該代碼片段進行編譯,該代碼片段由一個線性且連續的指令序列組成,僅有一個入口,但有多個出口。也就是說,基於蹤跡而編譯的熱點代碼不僅僅局限在一個單獨的方法或者代碼塊中,一條Trace可能對應多個方法,代碼中頻繁執行的路徑就可能被識別成不同的蹤跡。
優點:這種方法有着更高的精度,並且能夠避免編譯不是頻繁執行的代碼,減少不必要的編譯開銷。
缺點:這種方法的實現很復雜。
"不知道什么時候開始對你小心翼翼說話了,我記得我從前挺囂張的。"