Java開發(fā)人員都知道字節(jié)碼將由JRE(Java運行時環(huán)境)執(zhí)行。但許多人不知道JRE是Java虛擬機(JVM)的實現(xiàn)耗帕,它分析字節(jié)碼,解釋代碼并執(zhí)行它体啰。
作為開發(fā)人員嗽仪,了解JVM的體系結(jié)構(gòu)非常重要,因為它使我們能夠更有效地編寫代碼闻坚。在本文中,我們將更深入地了解Java中的JVM體系結(jié)構(gòu)以及JVM的不同組件窿凤。
什么是JVM雳殊?
一個虛擬機是一個軟件實現(xiàn)物理機。Java是在WORA(隨時隨地運行)的概念下開發(fā)的相种, 它在VM上運行。該編譯器 編譯Java文件轉(zhuǎn)換成一個Java 的.class文件箫措,則該.class文件輸入到JVM衬潦,它加載并執(zhí)行類文件。下面是JVM的體系結(jié)構(gòu)圖镀岛。
JVM架構(gòu)圖
JVM如何工作?
如上面的架構(gòu)圖所示驾锰,JVM分為三個主要子系統(tǒng):
- 類加載器子系統(tǒng)
- 運行時數(shù)據(jù)區(qū)
- 執(zhí)行引擎
1.類加載器子系統(tǒng)
Java的動態(tài)類加載功能由類加載器子系統(tǒng)處理。它加載耻瑟,鏈接赏酥。并在類運行時第一次引用類時初始化類文件,而不是編譯時裸扶。
1.1加載
這個組件將加載類。BootStrap類Loader魏保,Extension類Loader和Application類Loader是三個類加載器何荚,它將有助于實現(xiàn)它猪杭。
- Boot Strap ClassLoader - 負責(zé)從引導(dǎo)類路徑加載類,只有rt.jar皂吮。該裝載機將獲得最高優(yōu)先級。
- Extension ClassLoader - 負責(zé)加載ext文件夾(jre \ lib)中的類需纳。
- Application ClassLoader -負責(zé)加載應(yīng)用程序級別類路徑艺挪,路徑提到環(huán)境變量等。
上面的類加載器將在加載類文件時遵循委托層次結(jié)構(gòu)算法口蝠。
1.2鏈接
- 驗證 - 字節(jié)碼驗證程序?qū)Ⅱ炞C生成的字節(jié)碼是否正確津坑,如果驗證失敗,我們將收到驗證錯誤眉反。
- 準備 - 對于所有靜態(tài)變量,將分配內(nèi)存并為其分配默認值寸五。
- 解決 - 所有符號內(nèi)存引用都替換為方法區(qū)域中的原始引用。
1.3初始化
這是類加載的最后階段伶跷,這里 將為所有靜態(tài)變量分配原始值秘狞,并執(zhí)行靜態(tài)塊。
2.運行時數(shù)據(jù)區(qū)
運行時數(shù)據(jù)區(qū)分為5個主要組件:
方法區(qū)域 - 所有類級別數(shù)據(jù)都將存儲在此處烁试,包括靜態(tài)變量减响。每個JVM只有一個方法區(qū)域,它是一個共享資源支示。
堆區(qū)域 - 所有對象及其對應(yīng)的實例變量和數(shù)組將存儲在此處。每個JVM還有一個堆區(qū)域促绵。由于Method和Heap區(qū)域共享多個線程的內(nèi)存嘴纺,因此存儲的數(shù)據(jù)不是線程安全的。
-
堆棧區(qū)域
- 對于每個線程栽渴,將創(chuàng)建單獨的運行時堆棧。對于每個方法調(diào)用慢味,將在堆棧存儲器中創(chuàng)建一個條目墅冷,稱為堆棧幀。將在堆棧內(nèi)存中創(chuàng)建所有局部變量感昼。堆棧區(qū)域是線程安全的罐脊,因為它不是共享資源蜕琴。堆椣Γ框架分為三個子實體:
- 局部變量數(shù)組 - 與方法有關(guān),涉及多少局部變量恃逻,相應(yīng)的值將存儲在此處寇损。
- 操作數(shù)堆棧 - 如果需要執(zhí)行任何中間操作,則操作數(shù)堆棧充當(dāng)運行時工作空間以執(zhí)行操作矛市。
- 幀數(shù)據(jù) - 此方法存儲與該方法對應(yīng)的所有符號。在任何異常的情況下而昨,捕獲塊信息將保留在幀數(shù)據(jù)中找田。
PC寄存器 - 每個線程都有單獨的PC寄存器,一旦執(zhí)行指令就保持當(dāng)前執(zhí)行指令的地址墩衙,PC寄存器將用下一條指令更新底桂。
Native Method堆棧 - Native Method Stack保存本機方法信息惧眠。對于每個線程,將創(chuàng)建單獨的本機方法堆棧氛魁。
3.執(zhí)行引擎
分配給運行時數(shù)據(jù)區(qū)的字節(jié)碼將由執(zhí)行引擎執(zhí)行。執(zhí)行引擎讀取字節(jié)碼并逐個執(zhí)行捶码。
解釋器 - 解釋器更快地解釋字節(jié)碼或链,但執(zhí)行緩慢。解釋器的缺點是祈纯,當(dāng)一個方法被多次調(diào)用時,每次需要新的解釋時腕窥。
-
JIT編譯器
- JIT編譯器中和了解釋器的缺點。執(zhí)行引擎將使用解釋器的幫助來轉(zhuǎn)換字節(jié)代碼癞松,但是當(dāng)它找到重復(fù)的代碼時入蛆,它使用JIT編譯器,它編譯整個字節(jié)碼并將其更改為本機代碼厕妖。此本機代碼將直接用于重復(fù)的方法調(diào)用挑庶,從而提高系統(tǒng)的性能。
- 中間代碼生成器 - 生成中間代碼
- 代碼優(yōu)化器 - 負責(zé)優(yōu)化上面生成的中間代碼
- 目標代碼生成器 - 負責(zé)生成機器代碼或本機代碼
- Profiler - 一個特殊組件迎捺,負責(zé)查找熱點,即該方法是否被多次調(diào)用抄沮。
垃圾收集器:收集和刪除未引用的對象岖瑰。可以通過調(diào)用觸發(fā)垃圾收集
System.gc()
率挣,但不保證執(zhí)行露戒。JVM的垃圾收集收集創(chuàng)建的對象。
Java本機接口(JNI):JNI將與本機方法庫交互动漾,并提供執(zhí)行引擎所需的本機庫荠锭。
本機方法庫:這是執(zhí)行引擎所需的本機庫的集合。