淺析類加載過程與JVM內(nèi)存模型

java自從問世以來,一直號稱一處編譯,處處運(yùn)行。那么java的底層的是什么樣的呢?我們所熟知的JDK(Java Development Kit)其實(shí)是一個(gè)很大的東西,包含了JRE(Java Runtime Environment),Java 語言以及一些工具集。


Java平臺結(jié)構(gòu).png

一、 Java 類的加載過程

類加載過程.png

(一)、裝載(Load)

裝載(Loading) 是類加載的一個(gè)階段,需要Java 虛擬機(jī)來完成以下過程
1). 通過一個(gè)類將一個(gè)類的二進(jìn)制文件字節(jié)流讀取進(jìn)JVM中。
2). 將這些二進(jìn)制文件字節(jié)流裝載進(jìn)運(yùn)行時(shí)數(shù)據(jù)區(qū)中。
3). 在Java 堆中生成一個(gè)代表這個(gè)java 類的對象,并把它作為方法區(qū)的數(shù)據(jù)的入口。

(二)、鏈接(Link)

1).驗(yàn)證(Verify)

加載完成后,JVM就會(huì)去驗(yàn)證Class文件的格式,保證Class文件中包含的數(shù)據(jù)格式符合JVM的要求,且不會(huì)對JVM的自身安全造成影響。
如果您打開過class的二進(jìn)制文件就會(huì)知道前面4字節(jié)是cafe babe ,那這個(gè)又代表什么呢?通過下面官方提供的對照表可以知道,前面四個(gè)字節(jié)就是表明這個(gè)是一個(gè)標(biāo)識類的文件格式,U4 代表的是4字節(jié),U2代表是2字節(jié),按照這個(gè)對照表可以知道class二進(jìn)制文件中包含了類的主版本、次版本、方法、常量池等信息


Class類二進(jìn)制文件結(jié)構(gòu).png

加載過程中就會(huì)涉及到j(luò)ava加載機(jī)制-雙親委派機(jī)制
①. 類加載器收到加載請求;
②. 不會(huì)直接去加載,而是委托給其父類加載器去加載 ,直到Bootstrap加載器去加載;
③. 如果父類加載器無法加載則讓其子類加載器去加載;
④. 重復(fù)③,直到加載完成。
這樣做的一個(gè)好處就是可以避免一個(gè)類在JVM中多次加載,也可以避免JVM自身的類被修改,保證JVM的自身安全。
主要的JVM加載器
Bootstrap Class Loader : 主要加載 %JAVA_HOME%/jre/lib下java自帶的jar包;
Extension Class Loader : 主要加載 %JAVA_HOME%/jre/lib/ext下的jar包或者-Djava.ext.dirs指定目錄下的jar包
Application Class Loader : 主要加載 classpath指定的jar包以及-Djava.class.path指定目錄下的jar包
Custom Class Loader : 是java.lang.ClassLoader的子類自定義的加載類,通常加載自定義的類

2). 準(zhǔn)備(Prepare)

接下來就是準(zhǔn)備階段了,這一過程主要是為類的變量分配內(nèi)存并設(shè)置默認(rèn)值,這些內(nèi)存都是在方法區(qū)中分配的。這里只會(huì)分配final、static關(guān)鍵字修飾的變量,非這些關(guān)鍵字修飾的變量會(huì)在虛擬機(jī)棧中分配。

3). 解析(Resolve)

解析主要是將類中的符號引用變?yōu)橹苯右茫@里涉及類或接口的解析,字段的解析、類方法的解析、接口方法的解析。符號引用就是以一組符號的形式表示出一些特定的信息;直接引用就是就是將這些信息轉(zhuǎn)化為內(nèi)存地址或一個(gè)偏移量

(三)、初始化(Initialize)

類或接口的初始化包括執(zhí)行類或接口的初始化方法。Java虛擬機(jī)是多線程的,所以類或接口的初始化需要同步,因?yàn)槠渌恍┚€程可能同時(shí)嘗試初始化同一個(gè)類或接口。還可能遞歸地請求類或接口的初始化,作為該類或接口初始化的一部分。Java虛擬機(jī)的實(shí)現(xiàn)負(fù)責(zé)通過以下過程來處理同步和遞歸初始化。它假定Class對象已經(jīng)進(jìn)行了驗(yàn)證和準(zhǔn)備,而且Class對象包含的狀態(tài)指示了以下四種情況之一:

  • 對這個(gè)Class對象進(jìn)行了驗(yàn)證和準(zhǔn)備,但沒有初始化。
  • 這個(gè)Class對象是由某個(gè)特定線程初始化的。
  • 這個(gè)Class對象已經(jīng)完全初始化,可以使用了。
  • 這個(gè)Class對象處于錯(cuò)誤狀態(tài),可能是因?yàn)槌跏蓟瘒L試失敗。

二、JVM 內(nèi)存模型

JVM內(nèi)存模型就是在符合現(xiàn)有內(nèi)存模式的基礎(chǔ)上屏蔽了各種硬件和和操作系統(tǒng)的訪問差異的,保證了Java程序在各種平臺下對內(nèi)存的訪問都能保證效果一致的機(jī)制及規(guī)范,其主要的運(yùn)行時(shí)數(shù)據(jù)區(qū)處理相關(guān)差異。JVM定義了許多在程序運(yùn)行時(shí)的運(yùn)行數(shù)據(jù)區(qū)。一些數(shù)據(jù)區(qū)在隨著JVM生命周期活動(dòng),即與JVM的啟動(dòng)停止一致。另一些則和線程的生命周期相同,與線程同生共死。


JVM內(nèi)存模型.png

(一)、 方法區(qū)(Method Area)

方法區(qū)是在JVM中是所有線程所共享的,它存儲每個(gè)類的結(jié)構(gòu),例如運(yùn)行時(shí)常量池、字段和方法數(shù)據(jù),以及方法和構(gòu)造函數(shù)的代碼,包括類和實(shí)例初始化和接口初始化中使用的特殊方法。它是隨著JVM的啟動(dòng)而啟動(dòng)的,在邏輯上方法區(qū)是屬于堆的一部分,在JVM的規(guī)范中并沒有強(qiáng)制性的要求方法區(qū)進(jìn)行垃圾回收,而且方法區(qū)的大小可以固定也可以對其進(jìn)行擴(kuò)展,并沒有要求方法區(qū)的內(nèi)存空間是連續(xù)的,但是在方法區(qū)內(nèi)存不夠的時(shí)候會(huì)OutOfMemoryError

(二)、堆(Heap)

堆與方法區(qū)一樣是所有線程所共享的,也是隨著JVM的啟動(dòng)而啟動(dòng),它是為所有類實(shí)例或數(shù)組分配內(nèi)存的運(yùn)行時(shí)數(shù)據(jù)區(qū)域。該區(qū)域中的對象的堆存儲由垃圾回收機(jī)制回收。堆可以是固定大小的,也可以根據(jù)計(jì)算的要求進(jìn)行擴(kuò)展,如果沒有必要使用更大的堆,則可以縮小。堆的內(nèi)存同樣不需要是連續(xù)的。但是在堆內(nèi)存不夠的時(shí)候會(huì)OutOfMemoryError

(三)、虛擬機(jī)棧(Java Virtual Machine Stacks)

虛擬機(jī)棧是每個(gè)線程獨(dú)有的,隨著線程的創(chuàng)建而存在,線程結(jié)束而死亡。它存儲的是局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接和方法的出口等信息。但是在虛擬機(jī)棧內(nèi)存不夠的時(shí)候會(huì)OutOfMemoryError,在線程運(yùn)行中需要更大的虛擬機(jī)棧時(shí)會(huì)出現(xiàn)StackOverFlowError.

(四)、本地方法棧(Native Method Stacks)

本地方法棧允許java程序調(diào)用底層封裝的C語言編寫的方法實(shí)現(xiàn),如果在線程需要使用本地方法棧的時(shí)候,JVM會(huì)為每個(gè)線程創(chuàng)建一個(gè)。與虛擬機(jī)棧一樣在一些情況下會(huì)出現(xiàn)OutOfMemoryError或者StackOverFlowError

(五)、程序計(jì)數(shù)器(Program Counter Register)

由于JVM可以并發(fā)執(zhí)行線程,因此會(huì)存在線程之間的切換,而這個(gè)時(shí)候就程序計(jì)數(shù)器會(huì)記錄下當(dāng)前程序執(zhí)行到的位置,以便在其他線程執(zhí)行完畢后,恢復(fù)現(xiàn)場繼續(xù)執(zhí)行。JVM會(huì)為每個(gè)線程分配一個(gè)程序計(jì)數(shù)器,與線程的生命周期相同。

(六) 運(yùn)行時(shí)常量池(Runtime Constant Pool )

運(yùn)行時(shí)常量池是類文件中常量池表的運(yùn)行時(shí)形式,它包含編譯時(shí)已知的常量信息、必須在運(yùn)行時(shí)解析的方法和字段引用等信息。

任何形式的轉(zhuǎn)載都請聯(lián)系作者Jackieonway獲得授權(quán)并注明出處。
微信搜索"JackieOnWay"關(guān)注我們,第一時(shí)間獲取最新技術(shù)文摘。

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

相關(guān)閱讀更多精彩內(nèi)容

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