JVM(4)解釋器和即時編譯器

1、虛擬機運行模式

java是一種解釋性編程語言空盼,在Hotspot實現(xiàn)中,提供了解釋器和即時編譯器揽趾,即時編譯器能將熱點代碼編譯為效率更高的機器代碼,以提升執(zhí)行效率篱瞎,加快系統(tǒng)運行速度苟呐。

編譯.png

hotspot運行模式配置:

  • 解釋模式:可通過 -Xint 選項指定俐筋,讓 JVM 以解釋模式運行 Java 程序牵素。
  • 編譯模式:可通過 -Xcomp 選項指定,讓 JVM 以編譯模式運行 Java 程序澄者。
  • 混合模式:可通過 -Xmixed 選項指定,讓 JVM 以解釋+編譯模式運行 Java 程序粱挡,這也是 Hotspot 的默認模式.

2、解釋器

系統(tǒng)啟動時榕堰,解釋器按照預定義的規(guī)則逆屡,為所有字節(jié)碼分別創(chuàng)建能夠在具體計算機平臺上運行的機器碼魏蔗,并存放在特定位置勇蝙。當運行時環(huán)境需要解釋字節(jié)碼時味混,就到指定位置取出相應的code,直接在機器上運行诫惭。

3翁锡、即時編譯

解釋性語言的優(yōu)點是可移植性強,可以放在任何有解釋器的機器上運行夕土,但其運行性能較差馆衔。原因是解釋器需要實時將指令解釋為機器碼運行瘟判,而且解釋器未對指令做更好的優(yōu)化。

編譯器有足夠的上下文信息角溃、統(tǒng)計信息等拷获,可以對代碼進行更好的優(yōu)化。

3.1减细、編譯器類型

編譯器類型有client(C1編譯器)和server(C2編譯器)兩種類型匆瓜。兩種編譯器的主要差別是編譯代碼的時機不同。client編譯器在代碼執(zhí)行的開始階段未蝌,其編譯速度比server編譯器塊驮吱,而編譯的代碼比server編譯的多。server編譯器在編譯的時候會更好地進行優(yōu)化萧吠。

一種列外是分層編譯左冬,在虛擬機啟動時由client快速編譯,隨著代碼變熱后使用server編譯器重新編譯纸型,以提高系統(tǒng)的整體性能拇砰。

編譯器版本:

  • -client:32位client編譯器
  • -server:32位server編譯器
  • -d64:64位server編譯器
  • -XX:+TieredCompilation:分層編譯器,其使用server編譯器绊袋。

3.2毕匀、即時編譯器版本選擇

  • 32位系統(tǒng):必須選用32位的JVM,即client編譯器癌别;
  • 64位系統(tǒng):可選32位或64位皂岔。如果內(nèi)存小于3GB,32位編譯器更快展姐,占用內(nèi)存更少躁垛。因為虛擬機指針只有32位,所占內(nèi)存空間少圾笨,而且操作代價也少于64位的指針教馆。32位編譯器的缺點是內(nèi)存最多只能為4GB。而且還包括堆擂达、永久帶土铺、本地代碼及JVM所使用的本地內(nèi)存。另外板鬓,32位編譯器無法使用64位CPU的寄存器悲敷,無法進行寄存器相關的優(yōu)化,故大量使用long或double變量的應用會比較慢俭令。在 32 位 JVM 上運行的程序后德、只要與 32 位尋址空間吻合,無論機器是 32 位還是 64 位抄腔,都要比在類似配置的 64 位 JVM 上運行時快 5 %到 20 %瓢湃。

3.3理张、代碼緩存

虛擬機編譯時,會在代碼緩存中保留編譯之后的匯編語言指令集绵患。代碼緩存的大小固定雾叭,一旦填滿,虛擬機就不能編譯更多代碼了落蝙。故若代碼緩存過小拷况,只有少部分熱點代碼被編譯執(zhí)行,其他的則沒有掘殴,最終會導致大部分代碼都是解釋運行赚瘦,系統(tǒng)性能較差。

以上情況在client或分層編譯的情況下很常見奏寨。在使用常規(guī)server編譯器時起意,因通常只有少量類會被編譯,所以代碼緩存不太可能被填滿病瞳。而在client或分層編譯時揽咕,可被編譯的類可能會非常多。

參數(shù) 說明
-XX:CodeCacheExpansionSize 配置CodeCache空間擴展大小的參數(shù)
-XX:InitialCodeCacheSize 配置CodeCache空間的初始值
-XX:ReservedCodeCache 配置CodeCache空間的最大值
-XX:PrintCodeCache 退出時輸出CodeCache信息

3.4套菜、編譯閾值

觸發(fā)代碼編譯的主要因素是代碼執(zhí)行的頻度亲善,當執(zhí)行達到一定次數(shù),且到達編譯閾值逗柴,編譯器就可獲得足夠的信息進行代碼編譯了蛹头。

編譯時基于兩種計數(shù)器:方法調(diào)用計數(shù)器和方法中循環(huán)回邊計數(shù)器∠纺纾回邊為循環(huán)執(zhí)行的次數(shù)渣蜗。

虛擬機在執(zhí)行某個方法時,會檢查方法中的兩種計數(shù)器總數(shù)旷祸,然后判斷是否需要編譯耕拷。需要編譯則將該方法放入編譯隊列,進行標準編譯托享。

標準編譯由 -XX:CompileThreshold=N標志觸發(fā)骚烧,N=回邊計數(shù)器+方法調(diào)用次數(shù)。使用client編譯器時闰围,N默認值為1500赃绊,使用server編譯器時為10000。

實際上每種計數(shù)器的值都會周期性減少辫诅,計數(shù)器只是方法或循環(huán)最新熱度的度量凭戴。

3.5涧狮、編譯線程

編譯隊列中的任務是被后臺多個線程處理的炕矮。編譯隊列并不遵循先進先出的原則么夫,而是根據(jù)調(diào)用次數(shù)的多少作為優(yōu)先級。故當在出現(xiàn)開始執(zhí)行并有大量代碼需要編譯時肤视,最重要档痪、執(zhí)行次數(shù)最多的代碼會被優(yōu)先編譯。

當使用 client 編譯器時邢滑, JVM 會開啟一個編譯線程腐螟;使用 Server編譯器時,JVM 會開啟兩個這樣的線程困后。當啟用分層編譯時乐纸, JVM 默認開啟多個 client 和 server 線程,線程數(shù)依據(jù)一個略復雜的等式而定摇予,包括目標平臺 CPU 數(shù)取雙對數(shù)之后的數(shù)值汽绢。

編譯器的線程數(shù)( 3 種編譯器都是如此)可通過 -xx:CICompilerCount=N 標志來設置。這是JVM 處理隊列的線程總數(shù)侧戴;對分層編譯來說宁昭,其中三分之一(至少一個)將用來處理client 編譯器隊列,其余的線程(至少一個)用來處理 server編譯器隊列酗宋。

3.6积仗、內(nèi)聯(lián)

編譯器所做的最重要的優(yōu)化方法內(nèi)聯(lián)。面向?qū)ο笤O計都會有很多getter和setter方法蜕猫,此類方法調(diào)用開銷很大寂曹,特別是相對于方法的代碼量而言。當前的JVM都會用內(nèi)聯(lián)代碼的方式執(zhí)行這些方法回右。

內(nèi)聯(lián)是默認開啟的稀颁,可通過 -xx:-InLine關閉,然而其對性能影響巨大楣黍,最好不要關閉匾灶。

方法是否內(nèi)聯(lián)取決干它有多熱以及它的大小。 JVM 依據(jù)內(nèi)部計算來判定方法是否是熱點(譬如租漂,調(diào)用很頻繁)阶女;是否是熱點并不直接與任何調(diào)優(yōu)參數(shù)相關。如果方法因調(diào)用頻繁而可以內(nèi)聯(lián)哩治,那只有在它的字節(jié)碼小于 325 字節(jié)時(或 -XX:MaxFreqInlineSize = N 所設定的任意值)才會內(nèi)聯(lián)秃踩。否則,只有方法很小時业筏,即小于 35 字節(jié)(或 -xx : MaxlnlineSize = N 所設定的任意值)時才會內(nèi)聯(lián)憔杨。

有時你會看到增加MaxInlineSize 的值以便內(nèi)聯(lián)更多方法的建議。兩者之間常被忽略的是蒜胖,MaxInlineSize 超過35意味著第一次調(diào)用方法是就會被內(nèi)聯(lián)消别。然而抛蚤,方法只有經(jīng)常被調(diào)用時—在這種情況下它的性能會受更大影響― 最終才值得內(nèi)聯(lián)(假定它的大小小于 325 字節(jié))。否則寻狂,MaxInlineSize調(diào)用的最終結(jié)果就是減少了熱身測試所需要的時間岁经,但不太可能對長期運行的程序產(chǎn)生重大影響。

3.7蛇券、逃逸分析

如果開啟逃逸分析(-XX:DoEscapeAnalysist缀壤,默認為true),server編譯器會執(zhí)行一些非常激進的優(yōu)化措施纠亚。

4塘慕、分層編譯級別

當使用分層編譯時,編譯日志中會輸出代碼所編譯的分層級別蒂胞。

共5種編譯級別:

  • 0級:CompLevel_none苍糠,采用解釋器解釋執(zhí)行,不采集性能監(jiān)控數(shù)據(jù)啤誊,可以升級到1級岳瞭;
  • 1級:CompLevel_simple,采用C1編譯器蚊锹,會把熱點代碼迅速的編譯成本地代碼瞳筏,如果需要可以采用性能數(shù)據(jù);
  • 2級:CompLevel_limited_profile牡昆,采用C2編譯器姚炕,進行更好的優(yōu)化,甚至可能根據(jù)第1級采集的性能數(shù)據(jù)采取激進的優(yōu)化措施丢烘。
  • 3級:CompLevel_full_profile柱宦,采用C1編譯器,采集性能數(shù)據(jù)進行優(yōu)化措施播瞳;
  • 4級:CompLevel_full_optimization掸刊,采用C2編譯器,進行完全的優(yōu)化赢乓;

多數(shù)方法第一次編譯級別是3忧侧,即完全C1編譯,如果方法運行的足夠頻繁牌芋,它就會編譯成4蚓炬。

影響編譯策略的因素有兩個:

  • C2 隊列的長度決定了下一個等級.據(jù)觀察,第 2 級比第 3 級快約 30 % 躺屁,因此我們需要將一個 Java 方法花費在第 3 級上的時間盡可能地最小化.所以肯夏,若 C2隊列很長,直接選擇第 3 級會導致排隊,直到所提交的 C2 編譯請求通歷整個隊列.因此此時較為明智的做法是先使用第 2 級驯击,待 C2 負載回落烁兰,再啟動第 3 級重新編譯并開始收集性能數(shù)據(jù)。
  • C1 隊列的長度用來動態(tài)調(diào)整閾值余耽,從而在編譯器過載時引入額外的過濾.

如果server編譯器隊列滿了,就會從 server 隊列中取出方法苹熏,以級別 2 進行編譯碟贾,在這個級別上, C1 編譯器使用方法調(diào)用計數(shù)器和回邊計數(shù)器(但不需要性能分析的反饋信息)轨域。這使得方法編譯得更快袱耽,而方法也將在 C1 編譯器收集分析信息、之后被編譯為級別 3 干发,最終當 server 編譯器隊列不太忙的時候被編譯為級別 4 朱巨。

另一方面,如果client 編譯器全忙枉长,原本排程在級別 3 編譯的方法就既可以等待級別 3 編譯冀续,也適合進行級別 4 的編譯。在這種情況下必峰,方法編譯會很快轉(zhuǎn)到級別 2 洪唐,然后由級別 2 轉(zhuǎn)到級別 4 。

那些不太重要的方法可以從級別 2 或級別3 開始編譯吼蚁,但隨后會因為它們的重要性沒那么高而轉(zhuǎn)為級別 1 凭需。另外,如果 Server 編譯器出于某些原因無法編譯代碼肝匆,也會轉(zhuǎn)為級別 1粒蜈。當然,代碼在逆編譯時會轉(zhuǎn)為級別0 旗国。

有些標志可以控制某些級別轉(zhuǎn)換行為枯怖,但調(diào)優(yōu)能夠得到很樂觀的結(jié)果。當方法按期望的順序能曾,即級別 0 —>級別 3 —>級別 4 編譯時嫁怀,性能可以達到最優(yōu)。如果方法經(jīng)常被編譯為級別 2 借浊,并且還額外有可用的 CPU 周期塘淑,那就可以考慮增加編譯器的線程數(shù),從而減少 server編譯器隊列的長度蚂斤。如果沒有額外可用的 CPU 周期存捺,那你唯一能做的就是盡力減小應用的大小。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市捌治,隨后出現(xiàn)的幾起案子岗钩,更是在濱河造成了極大的恐慌,老刑警劉巖肖油,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兼吓,死亡現(xiàn)場離奇詭異,居然都是意外死亡森枪,警方通過查閱死者的電腦和手機视搏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來县袱,“玉大人浑娜,你說我怎么就攤上這事∈缴ⅲ” “怎么了筋遭?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長暴拄。 經(jīng)常有香客問我漓滔,道長,這世上最難降的妖魔是什么乖篷? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任次和,我火速辦了婚禮,結(jié)果婚禮上那伐,老公的妹妹穿的比我還像新娘踏施。我一直安慰自己,他們只是感情好罕邀,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布畅形。 她就那樣靜靜地躺著,像睡著了一般诉探。 火紅的嫁衣襯著肌膚如雪日熬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天肾胯,我揣著相機與錄音竖席,去河邊找鬼。 笑死敬肚,一個胖子當著我的面吹牛毕荐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播艳馒,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼憎亚,長吁一口氣:“原來是場噩夢啊……” “哼员寇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起第美,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤蝶锋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后什往,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扳缕,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年别威,在試婚紗的時候發(fā)現(xiàn)自己被綠了躯舔。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡兔港,死狀恐怖庸毫,靈堂內(nèi)的尸體忽然破棺而出仔拟,到底是詐尸還是另有隱情衫樊,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布利花,位于F島的核電站科侈,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏炒事。R本人自食惡果不足惜臀栈,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望挠乳。 院中可真熱鬧权薯,春花似錦、人聲如沸睡扬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卖怜。三九已至屎开,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間马靠,已是汗流浹背奄抽。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留甩鳄,地道東北人逞度。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像妙啃,于是被迫代替她去往敵國和親第晰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

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