類加載機制就是指虛擬機將類的數據從class文件加載到內存中,並對數據進行校驗、轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型。
生命週期:類從加載到內存到卸載出內存經歷了四個階段。加載、連接、初始化,使用。其中連接又分爲三步驟:驗證,準備,解析三個步驟。
類加載的時機:1、遇到new、putstatic、invokestatic等字節碼指令。eg:new一個對象;set/get類中的靜態字段;調用類中靜態方法。
2、在使用反射機制的時候、
3、初始化類時,若有 沒有初始化的父類。
一、加載
分爲以下幾步: 1、通過類的全限定名稱獲得該類的二進制字節流
2、將此字節流所代表的靜態存儲結構保存在方法區。
3、再內存中生成能代表這個類的class對象,作爲訪問方法區該類各種數據的入口。
類加載器:主要分爲三類加載器。
1、啓動類加載器:主要加載的是JVM自身需要的類。+lib/核心類庫 以java、javax、sun開頭的類
2、擴展類加載器:加載lib/ext目錄下的類
3、系統類加載器:加載classpath下的類
雙親委派模式的優勢:1、Java類隨着它的類加載器一起具備了一種帶有優先級的層次關係,通過這種層級關可以避免類的重複加載,當父親已經加載了該類時,就沒有必要子ClassLoader再加載一次
2、防止核心API庫被隨意篡改。當通過網絡傳遞一個啓動類已經加載過的類時,並不會根據網絡發來的類信息去加載,而是返回自己已經加載過的該類。
二、連接:
加載階段和連接階段(Linking)的部分內容(如一部分字節碼文件格式驗證動作)是交叉進行的,加載階段尚未完成,連接階段可能已經開始
1、驗證:確保class文件中包含的字節流中包含的信息符合當前虛擬機的要求。
a、文件格式驗證:是否以規定的魔數開頭,以此判斷該文件能否在當前虛擬機的處理範圍之內;當前文件中各部分是否有被刪除或附加的信息。
b、元數據驗證:站在類的角度檢測。是否有父類;是否繼承了不允許繼承的類;是否實現父類要求實現的方法;類中字段、方法是否與父類產生矛盾
c、字節碼驗證:進入類的內部去檢測。成員定義的數據類型是否與實際使用時的類型相等。(父類賦值子類、子類賦值父類)
d、符號引用驗證:將符號引用轉化爲直接引用。類的全限定命字符串是否能找到對應的類;是否能找到制定類的制定方法;是否有訪問資源的權限。
2、準備:爲類或接口的靜態字段分配空間併爲他們默認初始化。
public static int value = 123; 此時只是賦值爲0;
public static final int value = 123; 此時會賦值爲123
3、解析:將常量池中的符號引用替換成直接引用:
CONSTANT_CLASS_INFO =3;
三、初始化
執行<clinit>方法的過程。
<clinit>方法是由編譯器自動收集類中的所有類變量的賦值動作和靜態語句塊中的與聚合成的。(父類的靜態塊優於子類)
<clinit>是用於初始化靜態的類變量,<init>是初始化實例變量