JVM架構(gòu)和GC垃圾回收機(jī)制詳解

原文
JVM架構(gòu)圖分析

下圖:參考網(wǎng)絡(luò)+書籍,如有侵權(quán)請(qǐng)見諒?(想了解Hadoop內(nèi)存溢出請(qǐng)看:?Hadoop內(nèi)存溢出(OOM)分類、參數(shù)調(diào)優(yōu)化

JVM被分為三個(gè)主要的子系統(tǒng)

(1)類加載器子系統(tǒng)(2)運(yùn)行時(shí)數(shù)據(jù)區(qū)(3)執(zhí)行引擎

1. 類加載器子系統(tǒng)

Java的動(dòng)態(tài)類加載功能是由類加載器子系統(tǒng)處理。當(dāng)它在運(yùn)行時(shí)(不是編譯時(shí))首次引用一個(gè)類時(shí),它加載、鏈接并初始化該類文件。

1.1?加載

類由此組件加載。啟動(dòng)類加載器?(BootStrap class Loader)、擴(kuò)展類加載器(Extension class Loader)和應(yīng)用程序類加載器(Application class Loader)?這三種類加載器幫助完成類的加載。

1.? 啟動(dòng)類加載器?–?負(fù)責(zé)從啟動(dòng)類路徑中加載類,無非就是rt.jar。這個(gè)加載器會(huì)被賦予最高優(yōu)先級(jí)。

2.? 擴(kuò)展類加載器?–?負(fù)責(zé)加載ext?目錄(jre\lib)內(nèi)的類.

3.? 應(yīng)用程序類加載器?–?負(fù)責(zé)加載應(yīng)用程序級(jí)別類路徑,涉及到路徑的環(huán)境變量等etc.

上述的類加載器會(huì)遵循委托層次算法(Delegation Hierarchy Algorithm)加載類文件。

1.2?鏈接

1.? 校驗(yàn)?– 字節(jié)碼校驗(yàn)器會(huì)校驗(yàn)生成的字節(jié)碼是否正確,如果校驗(yàn)失敗,我們會(huì)得到校驗(yàn)錯(cuò)誤。

2.? 準(zhǔn)備?–?分配內(nèi)存并初始化默認(rèn)值給所有的靜態(tài)變量。

3.? 解析?–?所有符號(hào)內(nèi)存引用被方法區(qū)(Method Area)的原始引用所替代。

1.3?初始化

這是類加載的最后階段,這里所有的靜態(tài)變量會(huì)被賦初始值,?并且靜態(tài)塊將被執(zhí)行。

2.?運(yùn)行時(shí)數(shù)據(jù)區(qū)(Runtime Data Area)

The 運(yùn)行時(shí)數(shù)據(jù)區(qū)域被劃分為5個(gè)主要組件:

2.1 方法區(qū)(Method Area)

所有類級(jí)別數(shù)據(jù)將被存儲(chǔ)在這里,包括靜態(tài)變量。每個(gè)JVM只有一個(gè)方法區(qū),它是一個(gè)共享的資源。

2.2 堆區(qū)(Heap Area)

所有的對(duì)象和它們相應(yīng)的實(shí)例變量以及數(shù)組將被存儲(chǔ)在這里。每個(gè)JVM同樣只有一個(gè)堆區(qū)。由于方法區(qū)和堆區(qū)的內(nèi)存由多個(gè)線程共享,所以存儲(chǔ)的數(shù)據(jù)不是線程安全的。

2.3 棧區(qū)(Stack Area)

對(duì)每個(gè)線程會(huì)單獨(dú)創(chuàng)建一個(gè)運(yùn)行時(shí)棧。對(duì)每個(gè)函數(shù)呼叫會(huì)在棧內(nèi)存生成一個(gè)棧幀(Stack Frame)。所有的局部變量將在棧內(nèi)存中創(chuàng)建。棧區(qū)是線程安全的,因?yàn)樗皇且粋€(gè)共享資源。棧幀被分為三個(gè)子實(shí)體:

a 局部變量數(shù)組?–?包含多少個(gè)與方法相關(guān)的局部變量并且相應(yīng)的值將被存儲(chǔ)在這里。

b 操作數(shù)棧?–?如果需要執(zhí)行任何中間操作,操作數(shù)棧作為運(yùn)行時(shí)工作區(qū)去執(zhí)行指令。

c 幀數(shù)據(jù)?– 方法的所有符號(hào)都保存在這里。在任意異常的情況下,catch塊的信息將會(huì)被保存在幀數(shù)據(jù)里面。

2.4 PC寄存器

每個(gè)線程都有一個(gè)單獨(dú)的PC寄存器來保存當(dāng)前執(zhí)行指令的地址,一旦該指令被執(zhí)行,pc寄存器會(huì)被更新至下條指令的地址。

2.5 本地方法棧

本地方法棧保存本地方法信息。對(duì)每一個(gè)線程,將創(chuàng)建一個(gè)單獨(dú)的本地方法棧。

3. 執(zhí)行引擎

分配給運(yùn)行時(shí)數(shù)據(jù)區(qū)的字節(jié)碼將由執(zhí)行引擎執(zhí)行。執(zhí)行引擎讀取字節(jié)碼并逐段執(zhí)行。

3.1? 解釋器:

?解釋器能快速的解釋字節(jié)碼,但執(zhí)行卻很慢。 解釋器的缺點(diǎn)就是,當(dāng)一個(gè)方法被調(diào)用多次,每次都需要重新解釋。

編譯器

JIT編譯器消除了解釋器的缺點(diǎn)。執(zhí)行引擎利用解釋器轉(zhuǎn)換字節(jié)碼,但如果是重復(fù)的代碼則使用JIT編譯器將全部字節(jié)碼編譯成本機(jī)代碼。本機(jī)代碼將直接用于重復(fù)的方法調(diào)用,這提高了系統(tǒng)的性能。

a.?中間代碼生成器?– 生成中間代碼

b.?代碼優(yōu)化器?– 負(fù)責(zé)優(yōu)化上面生成的中間代碼

c.?目標(biāo)代碼生成器?– 負(fù)責(zé)生成機(jī)器代碼或本機(jī)代碼

d.? 探測(cè)器(Profiler)?– 一個(gè)特殊的組件,負(fù)責(zé)尋找被多次調(diào)用的方法。

3.3? 垃圾回收器:

收集并刪除未引用的對(duì)象??梢酝ㄟ^調(diào)用"System.gc()"來觸發(fā)垃圾回收,但并不保證會(huì)確實(shí)進(jìn)行垃圾回收。JVM的垃圾回收只收集哪些由new關(guān)鍵字創(chuàng)建的對(duì)象。所以,如果不是用new創(chuàng)建的對(duì)象,你可以使用finalize函數(shù)來執(zhí)行清理。

Java本地接口 (JNI):?JNI?會(huì)與本地方法庫(kù)進(jìn)行交互并提供執(zhí)行引擎所需的本地庫(kù)。

本地方法庫(kù):它是一個(gè)執(zhí)行引擎所需的本地庫(kù)的集合。

JVM三大核心區(qū)域



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容