摘要:用一張思維導(dǎo)圖盡可能囊括一下的類加載過程的全流程。本文參考自來自周志明深入理解虛擬機(jī)第版,拓展內(nèi)容建議讀者可以閱讀下這本書。
用一張思維導(dǎo)圖盡可能囊括一下JVM的類加載過程的全流程。
本文參考自來自周志明《深入理解Java虛擬機(jī)(第2版)》,拓展內(nèi)容建議讀者可以閱讀下這本書。
文字版如下:
加載 Loading 過程
通過類的全限定名來獲取定義此類的二進(jìn)制字節(jié)流
非數(shù)組類的加載,由類加載器加載,可以是啟動(dòng)類加載器,也可以是用戶自定義的類加載器
數(shù)組類的加載,不由類加載器創(chuàng)建,而是由JVM直接在內(nèi)部創(chuàng)建
組件類型(數(shù)組降一維后的類型)是引用類型,遞歸調(diào)用加載過程直到降到一維類型后通過類加載器加載,數(shù)組類型最終標(biāo)識(shí)為此類加載器所加載,數(shù)組類可見性和組件類型保持一致
組件類型不是引用類型而是原始類型,則該數(shù)組類型的類加載器將標(biāo)識(shí)為啟動(dòng)類加載器,數(shù)組類型可見性為public
將這個(gè)字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)
在內(nèi)存中(HotSpot為方法區(qū))生成一個(gè)代表了這個(gè)類的java.lang.Class對(duì)象,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)的訪問入口
類加載器啟動(dòng)類加載器 Bootstrap ClassLoader,加載
拓展類加載器 Extension ClassLoader,加載
應(yīng)用程序類加載器 Application ClassLoader,加載用戶類路徑上的ClassPath中的類
自定義類加載器 User ClassLoader
連接 Linking 驗(yàn)證 Verification
文件格式驗(yàn)證:字節(jié)流是否符合Class文件格式規(guī)范
是否以magic開頭
主次版本號(hào)是否在虛擬機(jī)處理范圍內(nèi)
常量池中的常量是否有不支持的類型
指向的常量索引值是否有指向不存在常量或不符合類型常量的情況
CONSTANT_Utf8_info的常量是否符合utf8編碼規(guī)范
Class文件各個(gè)部分及文件本身是否有被刪除或附加的其他信息
元數(shù)據(jù)驗(yàn)證:字節(jié)碼描述的信息進(jìn)行語(yǔ)義分析
是否有父類
父類是否繼承了不允許被繼承的類(final的)
如果不是抽象類是否實(shí)現(xiàn)了其父類或接口之中要求實(shí)現(xiàn)的類
類中字段、方法是否與父類產(chǎn)生矛盾
覆蓋了父類的final字段
不符合規(guī)范的方法重載?方法參數(shù)類型一致返回值類型不一致
字節(jié)碼驗(yàn)證:通過數(shù)據(jù)流和控制流分析程序語(yǔ)義的合法性,即類的方法體的校驗(yàn)分析
保證時(shí)刻操作數(shù)棧與指令代碼序列能配合工作
保證跳轉(zhuǎn)指令不會(huì)跳轉(zhuǎn)到方法體以外的字節(jié)碼指令上
保證方法體的類型轉(zhuǎn)換是有效的
符號(hào)引用驗(yàn)證:類的常量池中各種符號(hào)引用的信息進(jìn)行匹配性校驗(yàn)
符號(hào)引用中通過字符串描述的全限定名是否能找到對(duì)應(yīng)類
指定類中是否存在符合方法的字段描述符以及簡(jiǎn)單名稱所描述的方法和字段
符號(hào)引用中的類、字段和方法的訪問性是否可被當(dāng)前類所訪問
連接 Linking 驗(yàn)證 Verification
文件格式驗(yàn)證:字節(jié)流是否符合Class文件格式規(guī)范
是否以magic開頭
主次版本號(hào)是否在虛擬機(jī)處理范圍內(nèi)
常量池中的常量是否有不支持的類型
指向的常量索引值是否有指向不存在常量或不符合類型常量的情況
CONSTANT_Utf8_info的常量是否符合utf8編碼規(guī)范
Class文件各個(gè)部分及文件本身是否有被刪除或附加的其他信息
元數(shù)據(jù)驗(yàn)證:字節(jié)碼描述的信息進(jìn)行語(yǔ)義分析
是否有父類
父類是否繼承了不允許被繼承的類(final的)
如果不是抽象類是否實(shí)現(xiàn)了其父類或接口之中要求實(shí)現(xiàn)的類
類中字段、方法是否與父類產(chǎn)生矛盾
覆蓋了父類的final字段
不符合規(guī)范的方法重載?方法參數(shù)類型一致返回值類型不一致
字節(jié)碼驗(yàn)證:通過數(shù)據(jù)流和控制流分析程序語(yǔ)義的合法性,即類的方法體的校驗(yàn)分析
保證時(shí)刻操作數(shù)棧與指令代碼序列能配合工作
保證跳轉(zhuǎn)指令不會(huì)跳轉(zhuǎn)到方法體以外的字節(jié)碼指令上
保證方法體的類型轉(zhuǎn)換是有效的
符號(hào)引用驗(yàn)證:類的常量池中各種符號(hào)引用的信息進(jìn)行匹配性校驗(yàn)
符號(hào)引用中通過字符串描述的全限定名是否能找到對(duì)應(yīng)類
指定類中是否存在符合方法的字段描述符以及簡(jiǎn)單名稱所描述的方法和字段
符號(hào)引用中的類、字段和方法的訪問性是否可被當(dāng)前類所訪問
準(zhǔn)備 Preparation類變量分配空間
類變量分配零值
類常量分配初始值:由類字段的ConstantValue屬性進(jìn)行賦值
解析 Resolution
實(shí)際上就是把常量池中的符號(hào)引用替換為直接引用的過程
符號(hào)引用
在常量池中即非字面量的類型
CONSTANT_Class_info
CONSTANT_Fieldref_info
CONSTANT_Methodref_info
CONSTANT_InterfaceMethodref_info
…
特征
與虛擬機(jī)實(shí)現(xiàn)的內(nèi)存布局無關(guān)
引用的目標(biāo)并不一定已經(jīng)加載到內(nèi)存中
由虛擬機(jī)Class文件格式規(guī)范,因此不同虛擬機(jī)能夠接受的符號(hào)引用格式是確定的
直接引用
表達(dá)形式
直接指向目標(biāo)的虛擬機(jī)內(nèi)存中的指針
相對(duì)偏移量
能夠定位到目標(biāo)的句柄
特征
與虛擬機(jī)的內(nèi)存布局直接相關(guān)
引用的目標(biāo)必須已經(jīng)存在于內(nèi)存中
同一符號(hào)引用在不同虛擬機(jī)中的直接引用一般不同,由虛擬機(jī)自己制定格式
符號(hào)引用解析
類或接口的解析
對(duì)CONSTANT_Class_info符號(hào)引用的解析
對(duì)全限定名的解析
虛擬機(jī)加載類D中的類符號(hào)引用N為一個(gè)類或接口C的直接引用
C不是數(shù)組類型
虛擬機(jī)將N代表的全限定名傳遞給D的類加載器來加載C
C被成功加載后(可能是之前已經(jīng)加載過或者本次執(zhí)行了首次加載),虛擬機(jī)將D中的符號(hào)引用N替換為C的直接引用
符號(hào)引用驗(yàn)證,如D是否具備對(duì)C的訪問權(quán)限
C是數(shù)組類型?
虛擬機(jī)將N代表的全限定名(如[Ljava.lang.Integer)傳遞給D的類加載器來加載C(詳見數(shù)組類加載流程)
D的類加載器先加載C的組件類型(如java.lang.Integer)
虛擬機(jī)在方法區(qū)生成一個(gè)代表了數(shù)組維度和組件類型的數(shù)組對(duì)象
C被成功加載后,虛擬機(jī)將D中的符號(hào)引用N替換為C的直接引用
符號(hào)引用驗(yàn)證,如D是否具備對(duì)C的訪問權(quán)限
字段解析
對(duì)CONSTANT_Fieldref_info符號(hào)引用的解析
對(duì)class_index的解析
對(duì)nameAndType_index的解析
虛擬機(jī)在類D中加載字段符號(hào)引用N為字段F的直接引用
虛擬機(jī)在N中指定的類C里尋找字段描述符和N中指定的字段描述符一致的字段F
能找到,就將符號(hào)引用N替換為F的直接引用
符號(hào)引用驗(yàn)證,如D是否具備對(duì)F的訪問權(quán)限
找不到,在類C實(shí)現(xiàn)的接口中按照繼承關(guān)系從下向上尋找字段描述符和N中指定的字段描述符一致的字段F
能找到就將符號(hào)引用N替換為F的直接引用
符號(hào)引用驗(yàn)證,如D是否具備對(duì)F的訪問權(quán)限
找不到,在類C繼承的父類中按照繼承關(guān)系從下向上尋找字段描述符和N中指定的字段描述符一致的字段F
能找到就將符號(hào)引用N替換為F的直接引用
符號(hào)引用驗(yàn)證,如D是否具備對(duì)F的訪問權(quán)限
找不到,拋出java.lang.NoSuchFieldError異常
類方法解析
對(duì)CONSTANT_Methodref_info符號(hào)引用的解析
對(duì)class_index的解析
對(duì)nameAndType_index的解析
虛擬機(jī)在類D中加載類方法符號(hào)引用N為方法M的直接引用
虛擬機(jī)在N中指定的類C里尋找方法描述符和N中指定的方法描述符一致的方法M
能找到
class_index指定的類不是接口,就將符號(hào)引用N替換為M的直接引用
class_index指定的類是接口,拋出java.lang.IncompatibleClassChangeError異常
符號(hào)引用驗(yàn)證,如D是否具備對(duì)M的訪問權(quán)限
找不到,在類C繼承的父類中按照繼承關(guān)系從下向上尋找方法描述符和N中指定的方法描述符一致的方法M
能找到就將符號(hào)引用N替換為M的直接引用
符號(hào)引用驗(yàn)證,如D是否具備對(duì)M的訪問權(quán)限
找不到,在類C實(shí)現(xiàn)的接口中按照繼承關(guān)系從下向上尋找方法描述符和N中指定的方法描述符一致的方法M
能找到,說明類C是抽象類,拋出java.lang.AbstractMethodError異常(為什么說明C是抽象類呢?C的方法在C中找不到,但是在C實(shí)現(xiàn)的接口中找到了,這意味著C實(shí)現(xiàn)了接口但是沒有實(shí)現(xiàn)接口的這個(gè)方法,因此C類只可能是抽象類。)
找不到,拋出java.lang.NoSuchMethodError異常
接口方法解析
對(duì)CONSTANT_InterfaceMethodref_info符號(hào)引用的解析
對(duì)class_index的解析
對(duì)nameAndType_index的解析
虛擬機(jī)在類D中加載接口方法符號(hào)引用N為方法M的直接引用
虛擬機(jī)在N中指定的接口C里尋找方法描述符和N中指定的方法描述符一致的方法M
能找到
class_index指定的類是C接口,就將符號(hào)引用N替換為M的直接引用
class_index指定的類C不是接口,拋出java.lang.IncompatibleClassChangeError異常
符號(hào)引用驗(yàn)證,接口方法都是public的所以沒有訪問權(quán)限的問題
找不到,在接口C繼承的父接口中按照繼承關(guān)系從下向上尋找方法描述符和N中指定的方法描述符一致的方法M
能找到就將符號(hào)引用N替換為M的直接引用
找不到,拋出java.lang.NoSuchMethodError異常
初始化 Initialization 初始化就是執(zhí)行父類的
接口無靜態(tài)代碼塊但是可以用類變量賦值操作,因此也會(huì)生成
虛擬機(jī)會(huì)保證多線程環(huán)境下類的
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76792.html
摘要:本文是作者自己對(duì)中線程的狀態(tài)線程間協(xié)作相關(guān)使用的理解與總結(jié),不對(duì)之處,望指出,共勉。當(dāng)中的的數(shù)目而不是已占用的位置數(shù)大于集合番一文通版集合番一文通版垃圾回收機(jī)制講得很透徹,深入淺出。 一小時(shí)搞明白自定義注解 Annotation(注解)就是 Java 提供了一種元程序中的元素關(guān)聯(lián)任何信息和著任何元數(shù)據(jù)(metadata)的途徑和方法。Annotion(注解) 是一個(gè)接口,程序可以通過...
摘要:本文參考自來自周志明深入理解虛擬機(jī)第版,拓展內(nèi)容建議讀者可以閱讀下這本書。和構(gòu)造方法一一對(duì)應(yīng),是同一概念在兩個(gè)級(jí)別的含義收斂的操作自動(dòng)保證執(zhí)行父類的執(zhí)行語(yǔ)句塊初始化類變量字符串加操作替換為或的操作 showImg(https://segmentfault.com/img/remote/1460000016240419?w=3876&h=3614); 本文參考自來自周志明《深入理解Jav...
摘要:用于列舉最近分析過的文件常用功能欄,從左到右依次是概覽類直方圖支配樹查詢線程視圖報(bào)告相關(guān)詳細(xì)功能。針對(duì)那些占用堆內(nèi)存超過整個(gè)堆內(nèi)存大小的組件做一系列的分析,例如保留集合潛在的內(nèi)存浪費(fèi)問題等其他問題。 上一篇文章MAT入門到精通(一)介紹了MAT的使用場(chǎng)景和基本概念,這篇文章開始介紹MAT的基本功能,后面還有兩篇,一篇是MAT的高級(jí)功能,另一篇是MAT實(shí)戰(zhàn)案例分析。 三、歡迎頁(yè) 使用MA...
摘要:編譯器只需面向,生成能理解的代碼或字節(jié)碼文件。源文件經(jīng)編譯器,編譯成字節(jié)碼程序,通過將每一條指令翻譯成不同平臺(tái)機(jī)器碼,通過特定平臺(tái)運(yùn)行。漲見識(shí),字節(jié)碼執(zhí)行過程分析。解決辦法減少默認(rèn)棧的容量來?yè)Q取更多的線程支持。 前言 JVM是java的核心和基礎(chǔ),在java編譯器和os平臺(tái)之間的虛擬處理器。它是一種基于下層的操作系統(tǒng)和硬件平臺(tái)并利用軟件方法來實(shí)現(xiàn)的抽象的計(jì)算機(jī),可以在上面執(zhí)行java的...
摘要:編譯器只需面向,生成能理解的代碼或字節(jié)碼文件。源文件經(jīng)編譯器,編譯成字節(jié)碼程序,通過將每一條指令翻譯成不同平臺(tái)機(jī)器碼,通過特定平臺(tái)運(yùn)行。漲見識(shí),字節(jié)碼執(zhí)行過程分析。解決辦法減少默認(rèn)棧的容量來?yè)Q取更多的線程支持。 前言 JVM是java的核心和基礎(chǔ),在java編譯器和os平臺(tái)之間的虛擬處理器。它是一種基于下層的操作系統(tǒng)和硬件平臺(tái)并利用軟件方法來實(shí)現(xiàn)的抽象的計(jì)算機(jī),可以在上面執(zhí)行java的...
閱讀 1020·2021-11-25 09:43
閱讀 1679·2019-08-30 13:59
閱讀 1612·2019-08-30 11:22
閱讀 2137·2019-08-30 11:06
閱讀 1308·2019-08-28 17:51
閱讀 3744·2019-08-26 12:12
閱讀 790·2019-08-26 12:11
閱讀 456·2019-08-26 12:10