相關(guān)閱讀: 本文闡述了JVM的構(gòu)成和組件,配圖清晰易懂,是學(xué)習(xí)Java開發(fā)者的入門必讀文章。 每個(gè)Java開發(fā)人員都知道字節(jié)碼經(jīng)由JRE(Java運(yùn)行時(shí)環(huán)境)執(zhí)行。但他們或許不知道JRE其實(shí)是由Java虛擬機(jī)(JVM)實(shí)現(xiàn),JVM分析字節(jié)碼,解釋并執(zhí)行它。作為開發(fā)人員,了解JVM的架構(gòu)是非常重要的,因?yàn)樗刮覀兡軌蚓帉懗龈咝У拇a。本文中,我們將深入了解Java中的JVM架構(gòu)和JVM的各個(gè)組件。 JVM 虛擬機(jī)是物理機(jī)的軟件實(shí)現(xiàn)。Java的設(shè)計(jì)理念是WORA(Write Once Run Anywhere,一次編寫隨處運(yùn)行)。編譯器將Java文件編譯為Java .class文件,然后將.class文件輸入到JVM中,JVM執(zhí)行類文件的加載和執(zhí)行的操作。請(qǐng)看以下的JVM架構(gòu)圖: JVM是如何工作的? 如上面架構(gòu)圖所示,JVM分為三個(gè)主要子系統(tǒng):
1. 類加載器子系統(tǒng) Java的動(dòng)態(tài)類加載功能由類加載器子系統(tǒng)處理,處理過(guò)程包括加載和鏈接,并在類文件運(yùn)行時(shí),首次引用類時(shí)就開始實(shí)例化類文件,而不是在編譯時(shí)進(jìn)行。 1.1 加載 Boot Strap類加載器,Extension類加載器和Application(類加載器是實(shí)現(xiàn)類加載過(guò)程的三個(gè)類加載器。 (1) Boot Strap類加載器:負(fù)責(zé)從引導(dǎo)類路徑加載類,除了rt.jar,它具有最高優(yōu)先級(jí); (2) Extension 類加載器:負(fù)責(zé)加載ext文件夾(jre \ lib)中的類; (3) Application類加載器:負(fù)責(zé)加載應(yīng)用程序級(jí)類路徑,環(huán)境變量中指定的路徑等信息。 上面的類裝載器在加載類文件時(shí)遵循委托層次算法(Delegation Hierarchy Algorithm)。 1.2 鏈接 (1) 驗(yàn)證(Verify):字節(jié)碼驗(yàn)證器將驗(yàn)證生成的字節(jié)碼是否正確,如果驗(yàn)證失敗,將提示驗(yàn)證錯(cuò)誤; (2) 準(zhǔn)備(Prepare):對(duì)于所有靜態(tài)變量,內(nèi)存將會(huì)以默認(rèn)值進(jìn)行分配; (3) 解釋(Resolve):有符號(hào)存儲(chǔ)器引用都將替換為來(lái)自方法區(qū)(Method Area)的原始引用。 1.3 初始化 這是類加載的最后階段,所有的靜態(tài)變量都將被賦予原始值,并且靜態(tài)區(qū)塊將被執(zhí)行。 2. 運(yùn)行時(shí)數(shù)據(jù)區(qū) 運(yùn)行時(shí)數(shù)據(jù)區(qū)可分為5個(gè)主要組件: (1) 方法區(qū)(Method Area):所有的類級(jí)數(shù)據(jù)將存儲(chǔ)在這里,包括靜態(tài)變量。每個(gè)JVM只有一個(gè)方法區(qū),它是一個(gè)共享資源; (2) 堆區(qū)域(Heap Area):所有對(duì)象及其對(duì)應(yīng)的實(shí)例變量和數(shù)組將存儲(chǔ)在這里。每個(gè)JVM也只有一個(gè)堆區(qū)域。由于方法和堆區(qū)域共享多個(gè)線程的內(nèi)存,所存儲(chǔ)的數(shù)據(jù)不是線程安全的; (3) 堆棧區(qū)(Stack Area):對(duì)于每個(gè)線程,將創(chuàng)建單獨(dú)的運(yùn)行時(shí)堆棧。對(duì)于每個(gè)方法調(diào)用,將在堆棧存儲(chǔ)器中產(chǎn)生一個(gè)條目,稱為堆棧幀。所有局部變量將在堆棧內(nèi)存中創(chuàng)建。堆棧區(qū)域是線程安全的,因?yàn)樗还蚕碣Y源。堆??蚣芊譃槿齻€(gè)子元素:
(4) PC寄存器(PC Registers):每個(gè)線程都有單獨(dú)的PC寄存器,用于保存當(dāng)前執(zhí)行指令的地址。一旦執(zhí)行指令,PC寄存器將被下一條指令更新; (5) 本地方法堆棧(Native Method stacks):本地方法堆棧保存本地方法信息。對(duì)于每個(gè)線程,將創(chuàng)建一個(gè)單獨(dú)的本地方法堆棧。 3.執(zhí)行引擎 分配給運(yùn)行時(shí)數(shù)據(jù)區(qū)的字節(jié)碼將由執(zhí)行引擎執(zhí)行,執(zhí)行引擎讀取字節(jié)碼并逐個(gè)執(zhí)行。 (1) 解釋器:解釋器更快地解釋字節(jié)碼,但執(zhí)行緩慢。解釋器的缺點(diǎn)是當(dāng)一個(gè)方法被調(diào)用多次時(shí),每次都需要一個(gè)新的解釋; (2) JIT編譯器:JIT編譯器消除了解釋器的缺點(diǎn)。執(zhí)行引擎將在轉(zhuǎn)換字節(jié)碼時(shí)使用解釋器的幫助,但是當(dāng)它發(fā)現(xiàn)重復(fù)的代碼時(shí),將使用JIT編譯器,它編譯整個(gè)字節(jié)碼并將其更改為本地代碼。這個(gè)本地代碼將直接用于重復(fù)的方法調(diào)用,這提高了系統(tǒng)的性能。JIT的構(gòu)成組件為:
(3) 垃圾收集器(Garbage Collector):收集和刪除未引用的對(duì)象??梢酝ㄟ^(guò)調(diào)用“System.gc()”觸發(fā)垃圾收集,但不能保證執(zhí)行。JVM的垃圾回收對(duì)象是已創(chuàng)建的對(duì)象。 Java本機(jī)接口(JNI):JNI將與本機(jī)方法庫(kù)進(jìn)行交互,并提供執(zhí)行引擎所需的本機(jī)庫(kù)。 本地方法庫(kù)(Native Method Libraries):它是執(zhí)行引擎所需的本機(jī)庫(kù)的集合。 原文:The JVM Architecture Explained 作者:Jackson Joseraj 翻譯:Daisy |
|