JVM, 中文名是java虛擬機(jī), 正如它的名字, 是一個(gè)虛擬機(jī)器,來模擬通用的物理機(jī)。 JVM是一個(gè)標(biāo)準(zhǔn),一套規(guī)范, 規(guī)定了.class文件在其內(nèi)部運(yùn)行的相關(guān)標(biāo)準(zhǔn)和規(guī)范。 及其相關(guān)的內(nèi)部構(gòu)成。 比如:所有的JVM都是基于棧結(jié)構(gòu)的運(yùn)行方式。那么不符合這種要求的,不算是JVM, 如Android中所使用的Dalvik 虛擬機(jī)就不能稱作是JAVA 虛擬機(jī), 因?yàn)樗腔诩拇嫫鳎ㄗ钚碌腁ndroid系統(tǒng)據(jù)說已經(jīng)放棄了Dalvik VM, 而是使用ART)。
JVM相關(guān)的產(chǎn)品有很多, 通常最有名的莫過于現(xiàn)在Oracle公司所有的HotSpot 虛擬機(jī)。因此, 這里討論的都是HotSpot虛擬機(jī), 如果沒有特別說明。
被java編譯器(不僅限于, 還有其他任何的可以編輯成為.class的編譯器)編譯過的.class文件(可能是以jar、war、jsp等形式), 經(jīng)過類加載器加載 、 驗(yàn)證、準(zhǔn)備、解析、初始化之后, 才可以被使用。基本的過程如下:
加載: 首先,通過一個(gè)類的全類名來獲取此類的二進(jìn)制字節(jié)流。其次,將類中所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)換為運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu), 最后,生成一個(gè)代表加載的類的java.lang.Class對(duì)象, 作為方法區(qū)這個(gè)類的所有數(shù)據(jù)的訪問入口。加載完成之后, 虛擬機(jī)外部的二進(jìn)制靜態(tài)數(shù)據(jù)結(jié)構(gòu)就轉(zhuǎn)換成了虛擬機(jī)所需要的結(jié)構(gòu)存儲(chǔ)在方法區(qū)中(至于如何轉(zhuǎn)換, 則由具體虛擬機(jī)自己定義實(shí)現(xiàn)), 而所生成的Class對(duì)象, 則存放在方法區(qū)中, 用來作為程序訪問方法區(qū)中數(shù)據(jù)的外部接口。驗(yàn)證:其目的就是保證加載進(jìn)來的.class文件不會(huì)危害到虛擬機(jī)本身, 且內(nèi)容符合當(dāng)前虛擬機(jī)規(guī)范要求。主要驗(yàn)證的內(nèi)容大致有:文件格式、元數(shù)據(jù)驗(yàn)證、字節(jié)碼驗(yàn)證、符號(hào)引用驗(yàn)證。其中文件格式驗(yàn)證, 主要確保符合class文件格式規(guī)范(如文本后綴為.class的文件將驗(yàn)證不通過), 以及主次版本號(hào), 驗(yàn)證是否當(dāng)前JVM可以處理等。元數(shù)據(jù)驗(yàn)證,主要驗(yàn)證編譯后的字節(jié)碼描述信息是否符合java語法規(guī)范。字節(jié)碼驗(yàn)證, 其最為復(fù)雜, 主要通過控制流和數(shù)據(jù)流確定語義是否合法、符合邏輯。符號(hào)引用驗(yàn)證,可以看做是除自身以外(常量池中各種引用符號(hào))的信息匹配校驗(yàn),如通過持有的引用能否找到對(duì)應(yīng)的實(shí)例。準(zhǔn)備:正式為類變量分配內(nèi)存,并設(shè)置類變量的初始值。這些變量都會(huì)在方法區(qū)中進(jìn)行分配。解析:將常量池內(nèi)的符號(hào)引用替換為直接引用的過程。主要針對(duì)類或接口、字段、類方法、接口方法、方法類型、方法句柄等。初始化:加載的最后階段, 程序真正運(yùn)行的開始。方法區(qū):和java堆相同, 線程共享區(qū)域, 用來存儲(chǔ)已被虛擬機(jī)加載的類信息, 常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。有人稱作此方法區(qū)為“永久帶”, 本質(zhì)上不等價(jià),只是HotSpot VM將GC分代收集擴(kuò)展到了方法區(qū),這樣HotSpot的垃圾收集器管理方法區(qū)和管理java堆一樣(優(yōu)點(diǎn):不用專門為方法區(qū)寫一套垃圾收集器, 缺點(diǎn):容易導(dǎo)致內(nèi)存溢出)。官方現(xiàn)在擁也有放棄永久帶并改為采用Native Memory來實(shí)現(xiàn)方法區(qū)的計(jì)劃,目前已經(jīng)發(fā)布的JDK7中的HotSpot中, 已經(jīng)將原本放在方法區(qū)中的字符串常量池移出了。
運(yùn)行時(shí)常量池:是方法區(qū)的一部分。Class文件中除了有類的版本、字段、方法、接口等描述外,還有一項(xiàng)就是常量池, 用于存放編譯期間生成的各種字面量和符號(hào)引用 ,這部分內(nèi)容在類加載后進(jìn)入方法區(qū)的運(yùn)行時(shí)常量池中存放。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注