java開發(fā)者都知道JRE(Java Runtime Environment)會(huì)執(zhí)行字節(jié)碼。但是可能大多數(shù)人都不知道一個(gè)事實(shí):JRE是JVM的實(shí)現(xiàn)漓帚,它分析字節(jié)碼母债,解釋并執(zhí)行代碼。作為一個(gè)開發(fā)者,了解JVM的架構(gòu)是非常重要的毡们,這會(huì)讓我們寫的代碼更有效率迅皇。本文會(huì)深入學(xué)習(xí)JVM架構(gòu)和它的各個(gè)重要組件。
什么是JVM
虛擬機(jī)是物理機(jī)器的軟件實(shí)現(xiàn)衙熔。JAVA被設(shè)計(jì)成WORA(Write Once Run Anywhere), java程序是運(yùn)行在虛擬機(jī)上的登颓。編譯器將java文件編譯成.class文件,然后將.class文件載入到JVM红氯,這一步會(huì)加載和執(zhí)行class文件框咙。下面的圖是展示了JVM的架構(gòu)。
JVM 架構(gòu)圖
JVM如何工作
如上圖所示痢甘,jvm主要分成三個(gè)子系統(tǒng)
類加載系統(tǒng)
運(yùn)行時(shí)數(shù)據(jù)區(qū)
執(zhí)行引擎
類加載系統(tǒng)
java的動(dòng)態(tài)類加載功能在類加載子系統(tǒng)中實(shí)現(xiàn)喇嘱。當(dāng)?shù)谝淮卧谶\(yùn)行時(shí)(不是在編譯時(shí))涉及到一個(gè)class時(shí),它會(huì)加載塞栅,鏈接并初始化類文件者铜。
加載:類會(huì)通過(guò)這個(gè)組件加載。根加載器(rt.jar)放椰,擴(kuò)展加載器(jrelibext)和系統(tǒng)加載器(classpath下的)是其主要的工具作烟。
鏈接:主要分層三步
檢查:判斷其字節(jié)碼是否符合虛擬器要求
準(zhǔn)備:分配靜態(tài)變量的空間,同時(shí)賦缺省值
解析:解析符號(hào)鏈接砾医,鏈接到方法區(qū)的引用上去俗壹。
初始化:給靜態(tài)變量賦初值,并執(zhí)行靜態(tài)代碼區(qū)
運(yùn)行時(shí)數(shù)據(jù)區(qū)
運(yùn)行時(shí)數(shù)據(jù)區(qū)分成5個(gè)組件
方法區(qū):保存所有類數(shù)據(jù)藻烤,包括靜態(tài)變量。一個(gè)jvm對(duì)應(yīng)一個(gè)方法區(qū)头滔。
堆 :保存所有的對(duì)象怖亭,對(duì)象中的變量以及數(shù)組。一個(gè)jvm對(duì)應(yīng)一個(gè)堆坤检。因?yàn)槎鄠€(gè)線程共享一個(gè)方法區(qū)和堆兴猩,所以數(shù)據(jù)保存不是線程安全的。
棧:每一個(gè)線程都會(huì)創(chuàng)建一個(gè)運(yùn)行時(shí)的棧早歇。對(duì)于每一個(gè)方法調(diào)用倾芝,都會(huì)在棧中創(chuàng)建一個(gè)棧幀。棧中保存了所有的本地變量箭跳。棧是線程安全的晨另,因?yàn)樗蔷€程獨(dú)享資源。
PC寄存器:每個(gè)線程有一個(gè)PC寄存器谱姓,用來(lái)記錄當(dāng)前執(zhí)行指令的地址借尿,當(dāng)一條指令執(zhí)行完畢,它就會(huì)指向下一條指令。
本地方法棧:保存了本地方法的信息路翻,每個(gè)線程會(huì)創(chuàng)建自己的本地方法棧狈癞。
執(zhí)行引擎
字節(jié)碼加載到運(yùn)行時(shí)數(shù)據(jù)區(qū)后,會(huì)被執(zhí)行引擎執(zhí)行茂契。執(zhí)行引擎讀取字節(jié)碼文件蝶桶,逐個(gè)執(zhí)行。
解釋器:更快的解釋字節(jié)碼掉冶,但是執(zhí)行非常慢真竖。其缺點(diǎn)是當(dāng)多次調(diào)用一個(gè)方法時(shí),每次都會(huì)創(chuàng)建新的解釋器郭蕉。
JIT編譯器:JIT編譯器彌補(bǔ)了解釋器的缺點(diǎn)疼邀。執(zhí)行引擎會(huì)使用解釋器來(lái)轉(zhuǎn)換字節(jié)碼,當(dāng)發(fā)現(xiàn)重復(fù)的代碼時(shí)就會(huì)使用JIT編譯器召锈,它會(huì)編譯整個(gè)字節(jié)碼旁振,將之轉(zhuǎn)換為本地代碼,這個(gè)本地代碼會(huì)直接用于多次的方法調(diào)用涨岁,以此來(lái)改進(jìn)系統(tǒng)的性能拐袜。
垃圾收集:收集并移除不再被使用的對(duì)象∩倚剑可以通過(guò)代碼system.gc()來(lái)觸發(fā)垃圾收集蹬铺,