Java虛擬機(jī)之所以稱為“虛擬”,就是因?yàn)樗鼉H僅是由一個(gè)規(guī)范來定義的抽象計(jì)算機(jī)。要運(yùn)行某個(gè)Java程序,首先需要一個(gè)符合該規(guī)范的具體實(shí)現(xiàn)。下面主要討論這個(gè)規(guī)范本身。
Java虛擬機(jī)是什么
???要理解Java虛擬機(jī),你必須意識(shí)到,當(dāng)你說“Java虛擬機(jī)”時(shí),可能指的是如下三種不同的東西:
- 抽象規(guī)范?
- 一個(gè)具體的實(shí)現(xiàn)?
- 一個(gè)運(yùn)行中的虛擬機(jī)實(shí)例
Java虛擬機(jī)抽象規(guī)范僅僅是個(gè)概念。該規(guī)范的具體實(shí)現(xiàn),可能來自多個(gè)提供商,并存在多個(gè)平臺(tái)上。它或者完全用軟件實(shí)現(xiàn),或者以硬件和軟件相結(jié)合的方式來實(shí)現(xiàn)。當(dāng)運(yùn)行一個(gè)Java程序的同時(shí),也就在運(yùn)行了一個(gè)Java虛擬機(jī)實(shí)例。
Java虛擬機(jī)的生命周期
?? 一個(gè)運(yùn)行時(shí)的Java虛擬機(jī)實(shí)例的天職就是:負(fù)責(zé)運(yùn)行一個(gè)Java程序。當(dāng)啟動(dòng)一個(gè)Java程序時(shí),一個(gè)虛擬機(jī)實(shí)例也就誕生了。當(dāng)該程序關(guān)閉推出,這個(gè)虛擬機(jī)實(shí)例也就隨之消亡。每個(gè)Java程序都運(yùn)行在于自己的Java虛擬機(jī)實(shí)例中。Java虛擬機(jī)實(shí)例通過調(diào)用某個(gè)初始類的main()方法來運(yùn)行一個(gè)Java程序。而這個(gè)main()方法必須是public,static,返回值為void。main()方法作為該程序初始線程的起點(diǎn),任何其他的線程都是由這個(gè)初始線程啟動(dòng)的。
?? Java虛擬機(jī)內(nèi)部有兩種線程:守護(hù)線程和非守護(hù)線程。守護(hù)線程通常由虛擬機(jī)自己使用的,比如執(zhí)行垃圾收集任務(wù)的線程。但是,Java程序也可以把它的創(chuàng)建的任何線程標(biāo)記為守護(hù)線程。而Java程序中的初始線程,就是開始于main()的那個(gè),是非守護(hù)線程。只要有非守護(hù)線程在運(yùn)行,那么這個(gè)Java程序也在繼續(xù)運(yùn)行,只有該程序中所有的非守護(hù)線程都終止時(shí),虛擬機(jī)實(shí)例將自動(dòng)退出。
Java虛擬機(jī)的體系結(jié)構(gòu)
??Java虛擬機(jī)的結(jié)構(gòu)分為:類裝載子系統(tǒng),運(yùn)行時(shí)數(shù)據(jù)區(qū),執(zhí)行引擎,本地方法接口。其中運(yùn)行時(shí)數(shù)據(jù)區(qū)又分為:方法區(qū),堆,Java棧,PC寄存器,本地方法棧。
類裝載子系統(tǒng)
??Java虛擬機(jī)中,負(fù)責(zé)查找并裝載類型的那部分稱為類裝載子系統(tǒng)。
??Java虛擬機(jī)有兩種類裝載器:?jiǎn)?dòng)類裝載器和用戶自定義類裝載器。啟動(dòng)類裝載器是Java虛擬機(jī)實(shí)現(xiàn)的一部分。用戶自定義類裝載器是Java程序的一部分。
??類裝載器的動(dòng)作:
- 裝載---查找并裝載類型的二進(jìn)制數(shù)據(jù)
- 連接---執(zhí)行驗(yàn)證,準(zhǔn)備,以及解析(可選)
驗(yàn)證:確保被導(dǎo)入類型的正確性
準(zhǔn)備:為類變量分配內(nèi)存,并將其初始化為默認(rèn)值
把類型中的符號(hào)引用換為直接引用
- 初始化---把類變量初始化為正確的初始值
方法區(qū)
??在Java虛擬機(jī)中,被裝載類型的信息存儲(chǔ)在一個(gè)邏輯上被稱為方法區(qū)的內(nèi)存中。當(dāng)虛擬機(jī)裝載某個(gè)類型時(shí),它使用類裝載器定位相應(yīng)的class文件,然后讀入這個(gè)class文件,然后將它傳輸?shù)教摂M機(jī)中,緊接著虛擬機(jī)提取其中的類型信息,并將這些信息存儲(chǔ)到方法區(qū)。該類型中的類(靜態(tài))變量同樣也是存儲(chǔ)在方法區(qū)中。方法區(qū)的大小不必固定,可以根據(jù)需要?jiǎng)討B(tài)調(diào)整。方法區(qū)也可以被垃圾收集,因?yàn)樘摂M機(jī)允許通過用戶定義的類裝載器來動(dòng)態(tài)擴(kuò)展Java程序,因此,一些類也會(huì)成為“不再引用”的類。?
??對(duì)于每個(gè)裝載的類型,虛擬機(jī)都會(huì)在方法區(qū)中存儲(chǔ)以下類型信息:
- 這個(gè)類型的全限定名。
- 這個(gè)類型的直接超類的全限定名(除非是java.lang.Object,無超類)
- 這個(gè)類型是類類型還是接口類型。
- 這個(gè)類型的訪問修飾符(public,abstract ...)
- 任何直接超接口的全限定名的有序列表
除了上面列出的基本類型信息外,虛擬機(jī)還為每個(gè)被裝載的類型存儲(chǔ)以下信息
- 該類型的常量池
- 字段信息
- 方法信息
- 除了常量以外所有類(靜態(tài))變量
- 一個(gè)到類ClassLoader的引用
- 一個(gè)到Class類的引用
|