深入理解JVM學(xué)習(xí)筆記-運行期優(yōu)化

Java程序最初是通過解釋器進(jìn)行解釋執(zhí)行的痘绎,當(dāng)虛擬機發(fā)現(xiàn)某個方法或者代碼塊運行特別頻繁時兔毒,就會把這些代碼認(rèn)定為熱點代碼,為了提高熱點代碼的執(zhí)行效率纤怒,運行時虛擬機將會把熱點代碼編譯成與本地平臺相關(guān)的機器碼黄娘,并進(jìn)行各種層次的優(yōu)化峭状,完成這個任務(wù)的編譯器稱為即時編譯器克滴。即時編譯生成機器相關(guān)的中間碼,可重復(fù)執(zhí)行緩存效率高优床。解釋執(zhí)行直接執(zhí)行字節(jié)碼劝赔,重復(fù)執(zhí)行需要重復(fù)解釋。
即時編譯(JIT)與預(yù)編譯(AOT):在Dalvik下胆敞,應(yīng)用每次運行都需要通過即時編譯器(JIT)將字節(jié)碼轉(zhuǎn)換為機器碼着帽,即每次都要編譯加運行,這雖然會使安裝過程比較快移层,但是會拖慢應(yīng)用的運行效率仍翰。而在ART 環(huán)境中,應(yīng)用在第一次安裝的時候观话,字節(jié)碼就會預(yù)編譯(AOT)成機器碼予借,這樣的話,雖然設(shè)備和應(yīng)用的首次啟動(安裝慢了)會變慢频蛔,但是以后每次每次打開應(yīng)用灵迫,執(zhí)行的都是本地機器碼。移除了運行時的解釋執(zhí)行都可以直接運行晦溪,因此運行效率會提高瀑粥。Android7.0版本ART加入了即時編譯器JIT,作為AOT的一個補充三圆,在應(yīng)用程序安裝時并不會將字節(jié)碼全部編譯成機器碼利凑,在運行中將熱點代碼編譯成機器碼,從而縮短應(yīng)用程序的安裝時間并節(jié)省存儲空間嫌术。
解釋執(zhí)行:將編譯好的字節(jié)碼一行一行地翻譯為機器碼執(zhí)行。編譯執(zhí)行:以方法為單位牌借,將字節(jié)碼一次性翻譯為機器碼后執(zhí)行度气。當(dāng)程序需要迅速啟動和執(zhí)行時,解釋器可以首先發(fā)揮作用膨报,省去編譯的時間磷籍,立即執(zhí)行;當(dāng)程序運行后现柠,隨著時間的推移院领,編譯器逐漸會失去作用,把越來越多的代碼編譯成本地代碼后够吩,可以獲取更高的執(zhí)行效率比然。解釋執(zhí)行可以節(jié)約內(nèi)存,而編譯執(zhí)行可以提升效率周循。目前主流的HotSpot虛擬機中默認(rèn)是采用解釋器與其中一個編譯器直接配合的方式工作强法。

編譯對象與觸發(fā)條件

運行過程中會被即時編譯器編譯的熱點代有兩類:
(1)被多次調(diào)用的方法万俗。
(2)被多次調(diào)用的循環(huán)體。
以上兩種情況饮怯,編譯器都是以整個方法作為編譯對象闰歪,這種編譯也是虛擬機中標(biāo)準(zhǔn)的編譯方式。一段代碼或方法是不是熱點代碼蓖墅,是不是需要觸發(fā)即時編譯库倘,需要進(jìn)行Hot Spot Detection(熱點探測)。
目前主要的熱點 判定方式有以下兩種:
(1)基于采樣的熱點探測:虛擬機會周期性地檢查各個線程的棧頂论矾,如果發(fā)現(xiàn)某些方法經(jīng)常出現(xiàn)在棧頂教翩,那這段方法代碼就是“熱點代碼”。好處是:實現(xiàn)簡單高效拇囊,還可以很容易地獲取方法調(diào)用關(guān)系迂曲;缺點是:很難精確地確認(rèn)一個方法的熱度,容易因為受到線程阻塞或別的外界因素的影響而擾亂熱點探測寥袭。
(2)基于計數(shù)器的熱點探測:虛擬機會為每個方法路捧,甚至是代碼塊建立計數(shù)器,統(tǒng)計方法的執(zhí)行次數(shù)传黄,如果執(zhí)行次數(shù)超過一定的閥值杰扫,就認(rèn)為它是“熱點方法”。這種統(tǒng)計方法實現(xiàn)復(fù)雜一些膘掰,需要為每個方法建立并維護(hù)計數(shù)器章姓,而且不能直接獲取到方法的調(diào)用關(guān)系,但是它的統(tǒng)計結(jié)果相對更加精確嚴(yán)謹(jǐn)识埋。
在HotSpot虛擬機中使用的是第二種——基于計數(shù)器的熱點探測方法的兩個計數(shù)器:
(1)方法調(diào)用計數(shù)器:用來統(tǒng)計方法調(diào)用的次數(shù)凡伊,在默認(rèn)設(shè)置下,方法調(diào)用計數(shù)器統(tǒng)計的并不是方法被調(diào)用的絕對次數(shù)窒舟,而是一個相對的執(zhí)行頻率系忙,即一段時間內(nèi)方法被調(diào)用的次數(shù)。
(2)回邊計數(shù)器:用于統(tǒng)計一個方法中循環(huán)體代碼執(zhí)行的次數(shù).
(準(zhǔn)確地說惠豺,應(yīng)該是回邊的次數(shù)银还,因為并非所有的循環(huán)都是回邊),在字節(jié)碼中遇到控制流向后跳轉(zhuǎn)的指令就稱為“回邊”洁墙。
在確定虛擬機運行參數(shù)的前提下蛹疯,這兩個計數(shù)器都有一個確定的閥值,當(dāng)計數(shù)器的值超過了閥值热监,就會觸發(fā)JIT編譯捺弦。
即時編譯和解釋執(zhí)行的執(zhí)行順序:發(fā)了JIT編譯后,在默認(rèn)設(shè)置下,執(zhí)行引擎并不會同步等待編譯請求完成羹呵,而是繼續(xù)進(jìn)入解釋器按照解釋方式執(zhí)行字節(jié)碼骂际,直到提交的請求被編譯器編譯完成為止(編譯工作在后臺線程中進(jìn)行)。當(dāng)編譯工作完成后冈欢,下一次調(diào)用該方法或代碼時歉铝,就會使用已編譯的版本。方法調(diào)用計數(shù)器觸發(fā)即時編譯的流程:方法計數(shù)器觸發(fā)即時編譯的過程與回邊計數(shù)器觸發(fā)即時編譯的過程類似凑耻。方法調(diào)用計數(shù)器觸發(fā)即時編譯流程如下圖所示:

方法調(diào)用技術(shù)器觸發(fā)即時編譯.png

編譯優(yōu)化技術(shù)

以編譯方式執(zhí)行本地代碼比解釋方式更快太示,除去虛擬機執(zhí)行字節(jié)碼時額外消耗時間的原因外,還有一個重要原因香浩,虛擬機設(shè)計團(tuán)隊幾乎把對代碼的所有優(yōu)化措施都集中在了即時編譯器之中类缤,代碼優(yōu)化變換是建立在代碼的某種中間標(biāo)志或者機器碼之上,絕不是建立在java源碼之上的邻吭。華為方舟編譯器直接將代碼優(yōu)化從手機環(huán)節(jié)搬到了開發(fā)者環(huán)境餐弱,可以在很多地方對代碼進(jìn)行優(yōu)化,同時即時編譯器本地代碼比javac產(chǎn)生的的字節(jié)碼更優(yōu)秀囱晴。
即時編譯器針對不同的類型有不同的優(yōu)化技術(shù)膏蚓,具體可以參考《深入理解JVM》,幾種比較有代表性的優(yōu)化技術(shù)有:
(1)語言無關(guān)的經(jīng)典優(yōu)化技術(shù)之一:公共子表達(dá)式消除

int d = (C*B)*12 +a + (A+B*C)
int d = (E)*12 + a +A + E;
int d = 13E +2A;

以上就是公共子表達(dá)式消除畸写;
(2)語言相關(guān)的經(jīng)典優(yōu)化技術(shù)之一:數(shù)組范圍檢測消除:數(shù)組邊界檢查肯定是必須做的驮瞧,但是數(shù)組邊界檢查不是必須在運行期間一次不漏的檢查,如果通過數(shù)據(jù)流分析可以判斷循環(huán)變量的取值永遠(yuǎn)在數(shù)組邊界之內(nèi)枯芬,就可以在循環(huán)中將數(shù)組上下界檢測消除论笔。
(3)最重要的優(yōu)化技術(shù)之一:方法內(nèi)聯(lián):方法內(nèi)聯(lián)就是消除一些無用的代碼,如方法一已經(jīng)進(jìn)行了null判斷千所,如果調(diào)用方法二又進(jìn)行了null判斷狂魔,實際兩次null判斷僅需要一次。
(4)最前沿的優(yōu)化技術(shù)之一:逃逸分析:如果一個對象不會逃逸到方法或者線程之外淫痰,也就是別的方法或線程無法通過任何途徑訪問到這個對象毅臊,則可能為這個變量進(jìn)行一些高校的優(yōu)化,例如本來是堆上分配的變量發(fā)現(xiàn)沒有其他線程使用黑界,可以將其分配到棧上,棧上分配的對象就會隨著方法的結(jié)束而自動銷毀皂林。
(5)同步消除(synchronized):類似于鎖優(yōu)化朗鸠,變量不會逃逸到出方法,就可以將該方法上的同步鎖去掉础倍,相關(guān)內(nèi)容請參考《深入理解JVM》線程安全與鎖優(yōu)化章節(jié)烛占。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子忆家,更是在濱河造成了極大的恐慌犹菇,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芽卿,死亡現(xiàn)場離奇詭異揭芍,居然都是意外死亡,警方通過查閱死者的電腦和手機卸例,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門称杨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人筷转,你說我怎么就攤上這事姑原。” “怎么了呜舒?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵锭汛,是天一觀的道長。 經(jīng)常有香客問我袭蝗,道長唤殴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任呻袭,我火速辦了婚禮眨八,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘左电。我一直安慰自己廉侧,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布篓足。 她就那樣靜靜地躺著段誊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪栈拖。 梳的紋絲不亂的頭發(fā)上连舍,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機與錄音涩哟,去河邊找鬼索赏。 笑死,一個胖子當(dāng)著我的面吹牛贴彼,可吹牛的內(nèi)容都是我干的潜腻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼器仗,長吁一口氣:“原來是場噩夢啊……” “哼融涣!你這毒婦竟也來了童番?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤威鹿,失蹤者是張志新(化名)和其女友劉穎剃斧,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體忽你,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡幼东,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了檀夹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片筋粗。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖炸渡,靈堂內(nèi)的尸體忽然破棺而出娜亿,到底是詐尸還是另有隱情,我是刑警寧澤蚌堵,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布买决,位于F島的核電站,受9級特大地震影響吼畏,放射性物質(zhì)發(fā)生泄漏督赤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一泻蚊、第九天 我趴在偏房一處隱蔽的房頂上張望躲舌。 院中可真熱鬧,春花似錦性雄、人聲如沸没卸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽约计。三九已至,卻和暖如春迁筛,著一層夾襖步出監(jiān)牢的瞬間煤蚌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工细卧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留尉桩,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓贪庙,卻偏偏與公主長得像魄健,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子插勤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容