第7章 虛擬機類加載機制
類的加載的時機
加載 Loading, 連接 Linking(驗證 Verfiication, 準備PReparation, 解析 Resolution) 初始化 Initialization, 使用Using和卸載 Unloading
類加載的過程:
1,加載:
加載是“類加載" class loading過程珠一個階段,在加載階段,虛擬機需要完成以下3個事情。
1 通過一個類的全限定名來獲取定義此類的二進制字節流
2 將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構。
3 在內存中生成一個代表這個類的java.lang.Class對象,作為方法區這個類的各種數據的訪問入口。
2、驗證
1 文件格式驗證:驗證字節流是否符事Class文件格式的規范,并且能被當前版本的虛擬機處理。
2元數據驗證:對字節碼描述的信息進行語義分析。 這個類是否有父類,是否繼承了不允許被繼承的類。。。。
3 字節碼驗證:主要目的是通過數據流和控制流分析,確定程序語義是合法的、符合邏輯的。在第二階段對元數據信息中的數據類型做完校驗后,這個階段將對類的方法體進行校驗分析,保證被校驗類的方法在運行時不會做出危害虛擬機安全的事件。保證任意時刻操作數棧的數據類型與指令代碼序列都能配合工作,例如不會出現類似這樣的情況,在操作棧放置了一個int類型的數據,使用時卻按long類型來加載入本地變量表中。
4 符號引用驗證 最后一階段的校驗發生在虛擬機將符號引用轉化為直接引用的時候,這個轉化動作將在連接的第三階段--解析階段中發生。符號引用驗證可以看做是對類自身以外的信息進行匹配性校驗。 符號引用中通過字條串描述的全限定名是否能找到對應的類;在指定類中是否存在符合方法的字段描述符以及簡單名稱所描述的方法和字段............
3、準備
準備階段是正式為類變量分配內存并設置類變量初始值的階段。對于非靜態的變量,則不會為它們分配內存。
數據類型的初始值: int, byte, char, long, float, double默認初始值為0; boolean為false;reference為null.
對于常量屬性(public static final int value=23),在準備階段直接賦值23.
4、解析
解析階段是虛擬機將常量池內的符號引用替換為直接引用的過程。符號引用就是class格式中的CONSTANT_Class_info, CONSTANT_Fieldref_info, CONSTANT_Methodref_info及 CONSTANT_InterfaceMethodref_info的常量,直接引用就是直接指向目錄的指針、相對偏移量或一個間接前兩位到目標的句柄。有類或接口的解析,字段解析,類方法解析,接口方法解析。
5、初始化
是初始化類變量和其他資源,這里將執行用戶的static字段和靜態語句塊的賦值操作。這個過程執行類構造器<clinit>()方法的過程。
<clinit>()是郵編譯器自動收集類中的所有類變量的賦值動作和靜態語句塊(static{}塊)中的語句合并產生的,編譯器收集的順序是由語句在源文件中出現的順序所決定的。
1)如果類存在父類,并且父類沒有被初始化則先對直接父類進行初始化(執行父類的<clinit>()).
2)如果類妝前存在<clinit>()方法,則執行<clinit>()方法。
接口interface不能用static塊
類加載器
啟動類加載器 Bootstrap ClassLoader,主要負責加載java_home/lib目錄中的,或者被-Xbootclasspath參數所指定的路徑中的,并且可以是被擬機識別的類庫到虛擬機內存中。
擴展類加載器 Extension ClassLoader:這個加載器由sun.misc.Launcher$ExtClassLoader實現,負責加載java_home/lib/ext目錄中,或者被java.ext.dirs系統變量所指定的路徑中的類庫
應用程序類加載器 application ClassLoader:也叫系統類加載器。這個類加載器由sun.misc.Launcher$App-ClassLoader實現,主要負責加載classPath路徑上的類庫,如果應用程序沒有自定義自己類加載器,則這個就是默認的類加載器。
這三類加載器,不是父子關系,而是采用組合方式。正常情況下,每個類加在收到類加載請求時,會先調用父加載器進行加載,若父加載器加載失敗,則子加載器進行加載。只有父加載器不能加載該類時才會調用子加載器。
如需要加載java.lang.Object類時,不論使用哪個類加載器來加載,會找到根classLoader來加載該類。
新聞熱點
疑難解答