當(dāng)達(dá)到編譯閾值時,方法或循環(huán)就是進(jìn)入編譯隊列,在后臺異步地獲取隊列得代碼進(jìn)行編譯。
編譯隊列不是嚴(yán)格得先進(jìn)先出,執(zhí)行次數(shù)越多得代碼具有更高得優(yōu)先級。這也是在上一章節(jié),我們通過標(biāo)志PrintCompilation查看被編譯方法時,compilationg_id不完全按順序遞增得原因。
使用不同得編譯器,在不同平臺下會有不同得線程數(shù),與平臺得cpu數(shù)有關(guān)。
通常來說,使用client編譯器,則會開啟一個線程;使用server編譯器,則會開啟兩個線程。當(dāng)開啟分層編譯時,將會開啟多個線程,在不同得平臺得CPU數(shù)量下,線程數(shù)也會不同,在分層編譯器中,會將client編譯器稱為C1編譯器,將server編譯器稱為C2編譯器,我們下滿就這么稱呼它們,簡單列舉幾個情況:
cpu數(shù)量 | C1 | C2 |
1 | 1 | 1 |
2 | 1 | 1 |
4 | 1 | 2 |
8 | 1 | 2 |
16 | 2 | 6 |
32 | 3 | 7 |
64 | 4 | 8 |
128 | 4 | 10 |
我們通過標(biāo)志CICompilerCount來查看當(dāng)前jvm得線程數(shù)量,這是jvm處理編譯隊列得總線程數(shù):
[root等hecs-402944 opt]# jinfo -flag CICompilerCount 11210-XX:CICompilerCount=2復(fù)制代碼
我得服務(wù)器是2核,所以是2。其中包含一個client線程和server線程。
內(nèi)聯(lián)方法內(nèi)聯(lián)是編譯器當(dāng)中做得最重要得性能優(yōu)化。我們熟悉得java實體類,通常都會為每個屬性添加getter和setter方法,這種方法得調(diào)用相比于直接訪問變量,會有較大得性能開銷。
jvm當(dāng)中方法調(diào)用,存在于虛擬機(jī)棧得棧幀當(dāng)中,整個調(diào)用鏈較長,會有較大得性能損耗。
有如下得代碼:
static class Student { private String name; private String firstName; private String secondName; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getSecondName() { return secondName; } public void setSecondName(String secondName) { this.secondName = secondName; }}public static void main(String[] args) { Student student = new Student(); student.setName(student.getFirstName() + student.getSecondName());}復(fù)制代碼
在jvm幫助我們在編譯時進(jìn)行內(nèi)聯(lián)后,就會有如下得代碼:
public static void main(String[] args) { Student student = new Student(); student.name = student.firstName + student.secondName;}復(fù)制代碼
如上所示,已經(jīng)將get和set方法得調(diào)用進(jìn)行替換為直接屬性得調(diào)用。
可以通過如下方式查看內(nèi)聯(lián)屬性:
[root等hecs-402944 opt]# jinfo -flag Inline 11210-XX:+Inline復(fù)制代碼
默認(rèn)是開啟得,此參數(shù)對性能影響巨大,不建議關(guān)閉。
內(nèi)聯(lián)得條件觸發(fā)方法內(nèi)聯(lián)是有條件得,不是所有得代碼都會被內(nèi)聯(lián)。
是否可以被內(nèi)聯(lián)取決于方法代碼是否夠熱和它得大小。
逃逸分析簡單來說就是檢查變量,查看變量得使用位置,檢測其是否被其他范圍所使用。如果它沒有超出范圍,那就是一個局部變量,我們能夠針對這個變量做更多得優(yōu)化。
如果被外部得方法調(diào)用,則稱之為方法逃逸。 如果被外部得線程調(diào)用,則稱之為線程逃逸。
在java8當(dāng)中逃逸分析是默認(rèn)被開啟得:
[root等hecs-402944 opt]# jinfo -flag DoEscapeAnalysis 11210-XX:+DoEscapeAnalysis復(fù)制代碼
開啟逃逸分析后,server編譯器將會進(jìn)行很激進(jìn)得優(yōu)化:
當(dāng)然還有很多復(fù)雜得優(yōu)化,這里不過多介紹,因為不建議我們針對逃逸分析做優(yōu)化。
但是我們可以就逃逸分析解決一些問題:
原文鏈接:感謝分享juejin感謝原創(chuàng)分享者/post/7111091157240643615