JVM(八)內(nèi)存與垃圾回收|執(zhí)行引擎

本文介紹JVM的執(zhí)行引擎部分鹏漆。

目錄
?1 執(zhí)行引擎概述
??1.1 執(zhí)行引擎的工作過程
?2 Java代碼編譯和執(zhí)行過程
??2.1 解釋器
??2.2 JIT編譯器
??2.3 為什么說Java是半編譯半解釋型語言誊册?
?3 機(jī)器碼、指令香到、匯編語言、高級語言
??3.1 機(jī)器碼
??3.2 指令
??3.3 指令集
??3.4 匯編語言
??3.5 高級語言
??3.6 字節(jié)碼
?4 解釋器
??4.1 現(xiàn)狀
?5 JIT編譯器
??5.1 概念
??5.2 HotSpot VM 解釋器與JIT編譯器共存
???5.2.1 解釋器依然存在的必要性
???5.2.2 HotSpot VM 可以設(shè)置程序執(zhí)行方式
??5.3 熱點(diǎn)代碼及探測方式
???5.3.1 方法調(diào)用計(jì)數(shù)器
???5.3.2 回邊計(jì)數(shù)器
??5.4 HotSpot VM 中的JIT分類
???5.4.1 C1和C2編譯器不同的優(yōu)化策略
???5.4.2 分層編譯策略
???5.4.3 總結(jié)
?6 Graal編譯器與AOT編譯器
?? 6.1 Graal編譯器
?? 6.1 AOT編譯器


1 執(zhí)行引擎概述


  • 執(zhí)行引擎是Java虛擬機(jī)的核心組成部分之一


    執(zhí)行引擎
  • 虛擬機(jī)是一個(gè)相對于“物理機(jī)”的概念,這兩種機(jī)器都有代碼執(zhí)行能力午衰,其區(qū)別是物理機(jī)的執(zhí)行引擎是直接建立在處理器、緩存冒萄、指令集和操作系統(tǒng)層面上的臊岸,而虛擬機(jī)的執(zhí)行引擎則是由軟件自行實(shí)現(xiàn)的,因此可以不受物理?xiàng)l件制約地定制指令集與執(zhí)行引擎的結(jié)構(gòu)體系尊流,能夠執(zhí)行那些不被硬件直接支持的指令集格式帅戒。

  • JVM的主要任務(wù)是負(fù)責(zé)裝載字節(jié)碼到其內(nèi)部,但字節(jié)碼并不能夠直接運(yùn)行在操作系統(tǒng)之上崖技,因?yàn)樽止?jié)碼指令并非等價(jià)于本地機(jī)器指令蜘澜,它內(nèi)部包含的僅僅只是一些能夠被JVM鎖識(shí)別的字節(jié)碼指令、符號表和其他輔助信息

  • 那么响疚,如果想讓一個(gè)Java程序運(yùn)行起來鄙信、執(zhí)行引擎的任務(wù)就是將字節(jié)碼指令解釋/編譯為對應(yīng)平臺(tái)上的本地機(jī)器指令。簡單來說忿晕,JVM中的執(zhí)行引擎充當(dāng)了將高級語言翻譯為機(jī)器語言的譯者装诡。

1.1 執(zhí)行引擎的工作過程

  • 執(zhí)行引擎在執(zhí)行的過程中究竟需要執(zhí)行什么樣的字節(jié)碼指令完全依賴于PC寄存器。
  • 每當(dāng)執(zhí)行完一項(xiàng)指令操作后,PC寄存器就會(huì)更新下一條需要被執(zhí)行的指令地址鸦采。
  • 當(dāng)然方法在執(zhí)行的過程中宾巍,執(zhí)行引擎有可能會(huì)通過存儲(chǔ)在局部變量表中的對象引用準(zhǔn)確定位到存儲(chǔ)在Java堆區(qū)中的對象實(shí)例信息,以及通過對象頭中的元數(shù)據(jù)指針定位到目標(biāo)對象的類型信息渔伯。

2 Java代碼編譯和執(zhí)行過程


大部分的程序代碼轉(zhuǎn)換成物理機(jī)的目標(biāo)代碼或虛擬機(jī)能執(zhí)行的指令集之前顶霞,都需要經(jīng)過下面圖中的各個(gè)步驟:



Java代碼編譯是由Java源碼編譯器來完成,流程圖如下所示:



Java字節(jié)碼的執(zhí)行是由JVM執(zhí)行引擎來完成锣吼,流程圖如下所示:

2.1 解釋器

解釋器( Interpreter):當(dāng)Java虛擬機(jī)啟動(dòng)時(shí)會(huì)根據(jù)預(yù)定義的規(guī)范對字節(jié)碼采用逐行解釋的方式執(zhí)行选浑,將每條字節(jié)碼文件中的內(nèi)容“翻譯”為對應(yīng)平臺(tái)的本地機(jī)器指令執(zhí)行。

2.2 JIT編譯器

JIT (Just In Time Compiler)編譯器(即時(shí)編譯器):就是虛擬機(jī)將源代碼直接編譯成和本地機(jī)器平臺(tái)相關(guān)的機(jī)器語言玄叠。

2.3 為什么說Java是半編譯半解釋型語言古徒?

  • JDK1.0時(shí)代,將Java語言定位為“解釋執(zhí)行”還是比較準(zhǔn)確的读恃。再后來隧膘,Java也發(fā)展出可以直接生成本地代碼的編譯器。
  • 現(xiàn)在JVM在執(zhí)行Java代碼的時(shí)候寺惫,通常都會(huì)將解釋執(zhí)行編譯執(zhí)行二者結(jié)合起來進(jìn)行疹吃。

3 機(jī)器碼、指令西雀、匯編語言萨驶、高級語言


3.1 機(jī)器碼

  • 各種用二進(jìn)制編碼方式表示的指令,叫做機(jī)器指令碼蒋搜。開始篡撵,人們就用它采編寫程序,這就是機(jī)器語言豆挽。
  • 機(jī)器語言雖然能夠被計(jì)算機(jī)理解和接受育谬,但和人們的語言差別太大,不易被人們理解和記憶帮哈,并且用它編程容易出差錯(cuò)膛檀。
  • 用它編寫的程序一經(jīng)輸入計(jì)算機(jī),CPU直接讀取運(yùn)行娘侍,因此和其他語言編的程序相比咖刃,執(zhí)行速度最快
  • 機(jī)器指令與CPU緊密相關(guān)憾筏,所以不同種類的CPU所對應(yīng)的機(jī)器指令也就不同嚎杨。

3.2 指令

  • 由于機(jī)器碼是有0和1組成的二進(jìn)制序列,可讀性實(shí)在太差氧腰,于是人們發(fā)明了指令枫浙。
  • 指令就是把機(jī)器碼中特定的0和1序列刨肃,簡化成對應(yīng)的指令(一般為英文簡寫,如mov箩帚,inc等)真友,可讀性稍好
  • 由于不同的硬件平臺(tái),執(zhí)行同一個(gè)操作紧帕,對應(yīng)的機(jī)器碼可能不同盔然,所以不同的硬件平臺(tái)的同一種指令(比如mov),對應(yīng)的機(jī)器碼也可能不同是嗜。

3.3 指令集

  • 不同的硬件平臺(tái)愈案,各自支持的指令,是有差別的叠纷。因此每個(gè)平臺(tái)所支持的指令刻帚,稱之為對應(yīng)平臺(tái)的指令集潦嘶。
  • 如常見的
    • x86指令集涩嚣,對應(yīng)的是x86架構(gòu)的平臺(tái)
    • ARM指令集,對應(yīng)的是ARM架構(gòu)的平臺(tái)

3.4 匯編語言

  • 由于指令的可讀性還是太差掂僵,于是人們又發(fā)明了匯編語言航厚。
  • 在匯編語言中,用助記符(Mnemonics)代替機(jī)器指令的操作碼锰蓬,用地址符號(Symbol)或標(biāo)號(Label)代替指令或操作數(shù)的地址幔睬。
  • 在不同的硬件平臺(tái),匯編語言對應(yīng)著不同的機(jī)器語言指令集芹扭,通過匯編過程轉(zhuǎn)換成機(jī)器指令麻顶。
    • 由于計(jì)算機(jī)只認(rèn)識(shí)指令碼,所以用匯編語言編寫的程序還必須翻譯成機(jī)器指令碼舱卡,計(jì)算機(jī)才能識(shí)別和執(zhí)行辅肾。

3.5 高級語言

  • 為了使計(jì)算機(jī)用戶編程序更容易些,后來就出現(xiàn)了各種高級計(jì)算機(jī)語言轮锥。高級語言比機(jī)器語言矫钓、匯編語言更接近人的語言
  • 當(dāng)計(jì)算機(jī)執(zhí)行高級語言編寫的程序時(shí),仍然需要把程序解釋和編譯成機(jī)器的指令碼舍杜。完成這個(gè)過程的程序就叫做解釋程序或編譯程序新娜。

3.6 字節(jié)碼

  • 字節(jié)碼是一種中間狀態(tài)(中間碼)的二進(jìn)制代碼(文件),它比機(jī)器碼更抽象既绩,需要直譯器轉(zhuǎn)譯后才能成為機(jī)器碼
  • 字節(jié)碼主要為了實(shí)現(xiàn)特定軟件運(yùn)行和軟件環(huán)境概龄、與硬件環(huán)境無關(guān)
  • 字節(jié)碼的實(shí)現(xiàn)方式是通過編譯器和虛擬機(jī)饲握。編譯器將源碼編譯成字節(jié)碼私杜,特定平臺(tái)上的虛擬機(jī)將字節(jié)碼轉(zhuǎn)譯為可以直接執(zhí)行的指令吸重。

4 解釋器


  • JVM設(shè)計(jì)者們的初衷僅僅只是單純地為了滿足Java程序?qū)崿F(xiàn)跨平臺(tái)特性,因此避免采用靜態(tài)編譯的方式直接生成本地機(jī)器指令歪今,從而誕生了實(shí)現(xiàn)解釋器在運(yùn)行時(shí)采用逐行解釋字節(jié)碼執(zhí)行程序的想法嚎幸。

  • 解釋器真正意義上所承擔(dān)的角色就是一個(gè)運(yùn)行時(shí)“翻譯者”,將字節(jié)碼文件中的內(nèi)容“翻譯”為對應(yīng)平臺(tái)的本地機(jī)器指令執(zhí)行寄猩。

  • 當(dāng)一條字節(jié)碼指令被解釋執(zhí)行完成后嫉晶,接著再根據(jù)PC寄存器中記錄的下一條需要被執(zhí)行的字節(jié)碼指令執(zhí)行解釋操作。

  • 在Java的發(fā)展歷史里田篇,一共有兩套解釋執(zhí)行器替废,即古老的字節(jié)碼解釋器、現(xiàn)在普遍使用的模板解釋器泊柬。

  • 字節(jié)碼解釋器在執(zhí)行時(shí)通過純軟件代碼模擬字節(jié)碼的執(zhí)行椎镣,效率非常低下。 而模板解釋器將每一 條字節(jié)碼和一個(gè)模板函數(shù)相關(guān)聯(lián)兽赁,模板函數(shù)中直接產(chǎn)生這條字節(jié)碼執(zhí)行時(shí)的機(jī)器碼状答,從而很大程度上提高了解釋器的性能。

    • 在HotSpot VM中刀崖,解釋器主要由Interpreter模塊和Code模塊構(gòu)成惊科。
      • Interpreter模塊:實(shí)現(xiàn)了解釋器的核心功能
      • Code模塊:用于管理HotSpot VM在運(yùn)行時(shí)生成的本地機(jī)器指令

4.1 現(xiàn)狀

  • 由于解釋器在設(shè)計(jì)和實(shí)現(xiàn)上非常簡單,因此除了Java語言之外亮钦,還有許多高級語言同樣也是基于解釋器執(zhí)行的馆截,比如Python、 Perl蜂莉、Ruby等蜡娶。但是在今天,基于解釋器執(zhí)行已經(jīng)淪落為低效的代名詞映穗。
  • 為了解決這個(gè)問題窖张,JVM平臺(tái)支持一種叫作即時(shí)編譯的技術(shù)。即時(shí)編譯的目的是避免函數(shù)被解釋執(zhí)行男公,將整個(gè)函數(shù)體編譯成為機(jī)器碼荤堪,每次函數(shù)執(zhí)行時(shí),只執(zhí)行編譯后的機(jī)器碼即可枢赔,這種方式可以使執(zhí)行效率大幅度提升澄阳。
  • 不過無論如何,基于解釋器的執(zhí)行模式仍然為中間語言的發(fā)展做出了不可磨滅的貢獻(xiàn)踏拜。

5 JIT編譯器


5.1 概念

  • Java 語言的“編譯器” 其實(shí)是一段“不確定”的操作過程碎赢,因?yàn)樗赡苁侵敢粋€(gè)前端編譯器(其實(shí)叫“編譯器的前端” 更準(zhǔn)確一些)把.java文件轉(zhuǎn)變成.class文件的過程;
  • 也可能是指虛擬機(jī)的后端運(yùn)行期編譯器(JIT 編譯器速梗,Just In Time Compiler)把字節(jié)碼轉(zhuǎn)變成機(jī)器碼的過程肮塞。
  • 還可能是指使用靜態(tài)提前編譯器(AOT 編譯器襟齿,Ahead Of Time Compiler)直接把. java文件編譯成本地機(jī)器代碼的過程。

前端編譯器: Sun的Javac枕赵、 Eclipse JDT中的增量式編譯器(ECJ)
JIT編譯器: HotSpot VM的C1猜欺、C2編譯器。
AOT編譯器: GNU Compiler for the Java (GCJ) 拷窜、Excelsior JET开皿。

5.2 HotSpot VM 解釋器與JIT編譯器共存

??HotSpot VM是目前市面上高性能虛擬機(jī)的代表作之一。它采用解釋器與即時(shí)編譯器并存的架構(gòu)篮昧。在Java虛擬機(jī)運(yùn)行時(shí)赋荆,解釋器和即時(shí)編譯器能夠相互協(xié)作,各自取長補(bǔ)短懊昨,盡力去選擇最合適的方式來權(quán)衡編譯本地代碼的時(shí)間和直接解釋執(zhí)行代碼的時(shí)間窄潭。

5.2.1 解釋器依然存在的必要性

??既然HotSpotVM中已經(jīng)內(nèi)置JIT編譯器了,那么為什么還需要再使用解釋器來“拖累”程序的執(zhí)行性能呢酵颁?比如JRockit VM內(nèi)部就不包含解釋器嫉你,字節(jié)碼全部都依靠即時(shí)編譯器編譯后執(zhí)行。

??當(dāng)程序啟動(dòng)后材义,解釋器可以馬上發(fā)揮作用均抽,省去編譯的時(shí)間嫁赏,立即執(zhí)行其掂。 編譯器要想發(fā)揮作用,把代碼編譯成本地代碼潦蝇,需要一定的執(zhí)行時(shí)間款熬。但編譯為本地代碼后,執(zhí)行效率高攘乒。

??對于服務(wù)端應(yīng)用來說贤牛,啟動(dòng)時(shí)間并非是關(guān)注重點(diǎn),但對于那些看中啟動(dòng)時(shí)間的應(yīng)用場景而言则酝,或許就需要采用解釋器與即時(shí)編譯器并存的架構(gòu)來換取一一個(gè)平衡點(diǎn)殉簸。在此模式下,當(dāng)Java虛擬器啟動(dòng)時(shí)沽讹,解釋器可以首先發(fā)揮作用般卑,而不必等待即時(shí)編譯器全部編譯完成后再執(zhí)行,這樣可以省去許多不必要的編譯時(shí)間爽雄。隨著時(shí)間的推移蝠检,編譯器發(fā)揮作用,把越來越多的代碼編譯成本地代碼挚瘟,獲得更高的執(zhí)行效率叹谁。

??同時(shí)饲梭,解釋執(zhí)行在編譯器進(jìn)行激進(jìn)優(yōu)化不成立的時(shí)候,作為編譯器的“逃生門”焰檩。

5.2.2 HotSpot VM 可以設(shè)置程序執(zhí)行方式

缺省情況下HotSpot VM是采用解釋器與即時(shí)編譯器并存的架構(gòu)憔涉,當(dāng)然開發(fā)人員可以根據(jù)具體的應(yīng)用場景,通過命令顯式地為Java虛擬機(jī)指定在運(yùn)行時(shí)到底是完全采用解釋器執(zhí)行析苫,還是完全采用即時(shí)編譯器執(zhí)行监氢。如下所示:

  • -Xint: 完全采用解釋器模式執(zhí)行程序;
  • -Xcomp: 完全采用即時(shí)編譯器模式執(zhí)行程序藤违。如果即時(shí)編譯出現(xiàn)問題浪腐,解釋器會(huì)介入執(zhí)行。
  • -Xmixed:采用解釋器+即時(shí)編譯器的混合模式共同執(zhí)行程序顿乒。

5.3 熱點(diǎn)代碼及探測方式

??當(dāng)虛擬機(jī)啟動(dòng)的時(shí)候议街,解釋器可以首先發(fā)揮作用,而不必等待即時(shí)編譯器全部編譯完成再執(zhí)行璧榄,這樣可以省去許多不必要的編譯時(shí)間特漩。并且隨著程序運(yùn)行時(shí)間的推移,即時(shí)編譯器逐漸發(fā)揮作用骨杂,根據(jù)熱點(diǎn)探測功能涂身,將有價(jià)值的字節(jié)碼編譯為本地機(jī)器指令,以換取更高的程序執(zhí)行效率搓蚪。
??當(dāng)然是否需要啟動(dòng)JIT編譯器將字節(jié)碼直接編譯為對應(yīng)平臺(tái)的本地機(jī)器指令蛤售,則需要根據(jù)代碼被調(diào)用執(zhí)行的頻率而定

  • 一個(gè)被多次調(diào)用的方法妒潭,或者是一個(gè)方法體內(nèi)部循環(huán)次數(shù)較多的循環(huán)體都可以被稱之為熱點(diǎn)代碼悴能,因此都可以通過JIT編譯器編譯為本地機(jī)器指令。由于這種編譯方式發(fā)生在方法的執(zhí)行過程中雳灾,因此也被稱之為棧上替換漠酿,或簡稱為OSR (On StackReplacement)編譯
  • 一個(gè)方法究竟要被調(diào)用多少次谎亩,或者一個(gè)循環(huán)體究竟需要執(zhí)行多少次循環(huán)才可以達(dá)到這個(gè)標(biāo)準(zhǔn)炒嘲?必然需要一個(gè)明確的閾值,JIT編譯器才會(huì)將這些熱點(diǎn)代碼編譯為本地機(jī)器指令執(zhí)行匈庭。這里主要依靠熱點(diǎn)探測功能夫凸。
  • 目前HotSpot VM所采用的熱點(diǎn)探測方式是基于計(jì)數(shù)器的熱點(diǎn)探測
  • 采用基于計(jì)數(shù)器的熱點(diǎn)探測嚎花,HotSpot VM將會(huì)為每一個(gè) 方法都建立2個(gè)不同類型的計(jì)數(shù)器寸痢,分別為方法調(diào)用計(jì)數(shù)器(Invocation Counter)回邊計(jì)數(shù)器(BackEdge Counter)
    • 方法調(diào)用計(jì)數(shù)器用于統(tǒng)計(jì)方法的調(diào)用次數(shù)
    • 回邊計(jì)數(shù)器則用于統(tǒng)計(jì)循環(huán)體執(zhí)行的循環(huán)次數(shù)
5.3.1 方法調(diào)用計(jì)數(shù)器
  • 這個(gè)計(jì)數(shù)器就用于統(tǒng)計(jì)方法被調(diào)用的次數(shù)紊选,它的默認(rèn)閾值在Client 模式 下是1500 次啼止,在Server 模式下是10000 次道逗。超過這個(gè)閾值,就會(huì)觸發(fā)JIT編譯献烦。
  • 這個(gè)閾值可以通過虛擬機(jī)參數(shù)-XX :CompileThreshold來設(shè)定滓窍。
  • 當(dāng)一個(gè)方法被調(diào)用時(shí), 會(huì)先檢查該方法是否存在被JIT編譯過的版本巩那,如 果存在吏夯,則優(yōu)先使用編譯后的本地代碼來執(zhí)行。如果不存在已被編譯過的版本即横,則將此方法的調(diào)用計(jì)數(shù)器值加1噪生,然后判斷方法調(diào)用計(jì)數(shù)器與回邊計(jì)數(shù)器值之和是否超過方法調(diào)用計(jì)數(shù)器的閾值。如果已超過閾值东囚,那么將會(huì)向即時(shí)編譯器提交一個(gè)該方法的代碼編譯請求跺嗽。


熱度衰減

  • 如果不做任何設(shè)置,方法調(diào)用計(jì)數(shù)器統(tǒng)計(jì)的并不是方法被調(diào)用的絕對次數(shù)页藻,而是一個(gè)相對的執(zhí)行頻率桨嫁,即一段時(shí)間之內(nèi)方法被調(diào)用的次數(shù)。當(dāng)超過一定的時(shí)間限度份帐, 如果方法的調(diào)用次數(shù)仍然不足以讓它提交給即時(shí)編譯器編譯璃吧,那這個(gè)方法的調(diào)用計(jì)數(shù)器就會(huì)被減少一半,這個(gè)過程稱為方法調(diào)用計(jì)數(shù)器熱度的衰減(Counter Decay) 废境,而這段時(shí)間就稱為此方法統(tǒng)計(jì)的半衰周期(Counter Half Life Time)畜挨。
  • 進(jìn)行熱度衰減的動(dòng)作是在虛擬機(jī)進(jìn)行垃圾收集時(shí)順便進(jìn)行的,可以使用虛擬機(jī)參數(shù) -XX:-UseCounterDecay來關(guān)閉熱度衰減彬坏,讓方法計(jì)數(shù)器統(tǒng)計(jì)方法調(diào)用的絕對次數(shù)朦促,這樣,只要系統(tǒng)運(yùn)行時(shí)間足夠長栓始,絕大部分方法都會(huì)被編譯成本地代碼。
  • 另外血当, 可以使用-XX: CounterHalfLifeTime參數(shù)設(shè)置半衰周期的時(shí)間幻赚,單位是秒。
5.3.2 回邊計(jì)數(shù)器

它的作用是統(tǒng)計(jì)一個(gè)方法中循環(huán)體代碼執(zhí)行的次數(shù)臊旭,在字節(jié)碼中遇到控制流向后跳轉(zhuǎn)的指令稱為“回邊” (Back Edge)落恼。顯然,建立回邊計(jì)數(shù)器統(tǒng)計(jì)的目的就是為了觸發(fā)OSR編譯离熏。


5.4 HotSpot VM 中的JIT分類

在HotSpot VM中內(nèi)嵌有兩個(gè)JIT編譯器佳谦,分別為Client CompilerServer Compiler,但大多數(shù)情況下我們簡稱為C1編譯器和C2編譯器滋戳。開發(fā)人員可以通過如下命令顯式指定Java虛擬機(jī)在運(yùn)行時(shí)到底使用哪一種即時(shí)編譯器钻蔑,如下所示:

-client: 指定Java虛擬機(jī)運(yùn)行在Client模式下啥刻,并使用C1編譯器;C1編譯器會(huì)對字節(jié)碼進(jìn)行簡單和可靠的優(yōu)化咪笑,耗時(shí)短可帽。以達(dá)到更快的編譯速度。

-server: 指定Java虛擬機(jī)運(yùn)行在Server模式下窗怒,并使用C2編譯器映跟。C2進(jìn)行耗時(shí)較長的優(yōu)化,以及激進(jìn)優(yōu)化扬虚。但優(yōu)化的代碼執(zhí)行效率更高努隙。

5.4.1 C1和C2編譯器不同的優(yōu)化策略
  • C1編譯器上主要有方法內(nèi)聯(lián)去虛擬化辜昵、冗余消除剃法。

方法內(nèi)聯(lián):將引用的函數(shù)代碼編譯到引用點(diǎn)處,這樣可以減少棧幀的生成路鹰,減少參數(shù)傳遞以及跳轉(zhuǎn)過程
去虛擬化:對唯一的實(shí)現(xiàn)類進(jìn)行內(nèi)聯(lián)
冗余消除:在運(yùn)行期間把一些不會(huì)執(zhí)行的代碼折疊掉

  • C2的優(yōu)化主要是在全局層面贷洲,逃逸分析是優(yōu)化的基礎(chǔ)〗基于逃逸分析在C2上有如下幾種優(yōu)化:(server模式下才會(huì)有這些優(yōu)化优构,64位系統(tǒng)默認(rèn)就是server模式)

標(biāo)量替換:用標(biāo)量值代替聚合對象的屬性值
棧上分配:對于未逃逸的對象分配對象在棧而不是堆
同步消除:清除同步操作,通常指synchronized

5.4.2 分層編譯策略

分層編譯(Tiered Compilation)策略:程序解釋執(zhí)行(不開啟性能監(jiān)控)可以觸發(fā)C1編譯雁竞,將字節(jié)碼編譯成機(jī)器碼钦椭,可以進(jìn)行簡單優(yōu)化,也可以加上性能監(jiān)控碑诉,C2編譯會(huì)根據(jù)性能監(jiān)控信息進(jìn)行激進(jìn)優(yōu)化彪腔。
??不過在Java7版本之后,一旦開發(fā)人員在程序中顯式指定命令“一server"時(shí)进栽,默認(rèn)將會(huì)開啟分層編譯策略德挣,由C1編譯器和C2編譯器相互協(xié)作共同來執(zhí)行編譯任務(wù)。

5.4.3 總結(jié)

??一般來講快毛,JIT編譯出來的機(jī)器碼性能比解釋器高格嗅。
??C2編譯器啟動(dòng)時(shí)長比C1編譯器慢,系統(tǒng)穩(wěn)定執(zhí)行以后唠帝,C2編譯器執(zhí)行速度遠(yuǎn)遠(yuǎn)快于C1編譯器屯掖。

6 Graal編譯器與AOT編譯器


6.1 Graal編譯器

??自JDK10起,HotSpot又加入一個(gè)全新的即時(shí)編譯器: Graal編譯器編譯效果短短幾年時(shí)間就追評了C2編譯器襟衰。

??目前贴铜,Graal編譯器帶著“實(shí)驗(yàn)狀態(tài)"標(biāo)簽,需要使用開關(guān)參數(shù)-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler去激活,才可以使用绍坝。

6.2 AOT編譯器

??jdk9引入了AOT編譯器(靜態(tài)提前編譯器徘意,Ahead Of Time Compiler)

??Java 9引入了實(shí)驗(yàn)性AOT編譯工具jaotc。它借助了Graal 編譯器陷嘴,將所輸入的Java 類文件轉(zhuǎn)換為機(jī)器碼映砖,并存放至生成的動(dòng)態(tài)共享庫之中。

??所謂AOT編譯灾挨,是與即時(shí)編譯相對立的一個(gè)概念邑退。我們知道,即時(shí)編譯指的是在程序的運(yùn)行過程中劳澄,將字節(jié)碼轉(zhuǎn)換為可在硬件上直接運(yùn)行的機(jī)器碼地技,并部署至托管環(huán)境中的過程。而AOT編譯指的則是秒拔,在程序運(yùn)行之前莫矗,便將字節(jié)碼轉(zhuǎn)換為機(jī)器碼的過程。

??最大好處: Java虛擬機(jī)加載已經(jīng)預(yù)編譯成二進(jìn)制庫砂缩,可以直接執(zhí)行作谚。不必等待即時(shí)編譯器的預(yù)熱,減少Java應(yīng)用給人帶來“第一次運(yùn)行慢”的不良體驗(yàn)庵芭。

??缺點(diǎn):

  • 破壞了java"一次編譯妹懒,到處運(yùn)行”,必須為每個(gè)不同硬件双吆、oS編譯對應(yīng)的發(fā)行包眨唬。
  • 降低了Java鏈接過程的動(dòng)態(tài)性,加載的代碼在編譯期就必須全部已知好乐。
  • 還需要繼續(xù)優(yōu)化中匾竿,最初只支持Linux x64 java base
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蔚万,隨后出現(xiàn)的幾起案子岭妖,更是在濱河造成了極大的恐慌,老刑警劉巖笛坦,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件区转,死亡現(xiàn)場離奇詭異,居然都是意外死亡版扩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門侄泽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來礁芦,“玉大人,你說我怎么就攤上這事∈量郏” “怎么了肖方?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長未状。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么连舍? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任兜喻,我火速辦了婚禮,結(jié)果婚禮上埋虹,老公的妹妹穿的比我還像新娘猜憎。我一直安慰自己,他們只是感情好搔课,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布胰柑。 她就那樣靜靜地躺著,像睡著了一般爬泥。 火紅的嫁衣襯著肌膚如雪柬讨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天袍啡,我揣著相機(jī)與錄音踩官,去河邊找鬼。 笑死葬馋,一個(gè)胖子當(dāng)著我的面吹牛卖鲤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播畴嘶,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蛋逾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了窗悯?” 一聲冷哼從身側(cè)響起区匣,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蒋院,沒想到半個(gè)月后亏钩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡欺旧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年姑丑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辞友。...
    茶點(diǎn)故事閱讀 39,739評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡栅哀,死狀恐怖震肮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情留拾,我是刑警寧澤戳晌,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站痴柔,受9級特大地震影響沦偎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜咳蔚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一豪嚎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧屹篓,春花似錦疙渣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谍肤,卻和暖如春啦租,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背荒揣。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工篷角, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人系任。 一個(gè)月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓恳蹲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親俩滥。 傳聞我的和親對象是個(gè)殘疾皇子嘉蕾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評論 2 354