Java類裝載過程

字號:


    類裝載過程由JVM類裝載子系統(tǒng)負責,主要包括一下三個步驟:
    1)裝載:查找并裝載類型的二進制數據到虛擬機中
    1.通過某些途徑,產生一個代表該類型的二進制數據流
    2.解析二進制數據流為方法區(qū)的內部數據結構
    3.在堆中創(chuàng)建一個表示該類型的Class實例(裝載步驟的最終產品)
    注意:Java虛擬機規(guī)范允許類裝載器緩存Java類型的二進制表現(xiàn)形式,如果預裝載出錯,則要等待該類被主動使用時拋出LinkageError的子類的異常
    2)連接:
    1.驗證 確保導入的類格式正確
    檢查final類不能有子類,final方法不能被覆蓋,常量池檢查,字節(jié)碼完整性檢查...
    注意:Java虛擬機設計者可以決定如何及時驗證類型。Java虛擬機規(guī)范列出了虛擬機可以拋出的異常以及在何種條件下必須拋出它們
    2.準備 為類變量分配內存,設置默認初始值
    3.解析 把類型中的符號引用轉換為直接引用(也可能推遲到真正需要使用某個符號引用時再去解析它)
    在類型的常量池中尋找類,接口,字段和方法的符號引用,把類型中的符號引用轉換為直接引用
    3)初始化:把類變量初始化為正確的初始值
    1.如果類存在直接超類,且直接超類還沒有初始化,則先初始化直接超類
    2.如果類存在一個類初始化方法(“<clinit>”,并不是所有的類都存在這個方法,如果一個類沒有類變量也沒有靜態(tài)初始化語句,就沒有該方法),就執(zhí)行它
    所有的類變量初始化語句和類型的靜態(tài)初始化器都被Java編譯器收集在一起,放到一個特殊的方法(“<clinit>”)中,稱為類初始化方法,此方法只能被Java虛擬機調用
    所有的Java虛擬機實現(xiàn)必須在每個類或接口首次主動使用時初始化。有以下六種
    1)當創(chuàng)建某個類的新實例時,或者在字節(jié)碼中執(zhí)行new指令,或者通過不明確的創(chuàng)建、反射、克隆或者反序列化時。
    2)當調用某個類的靜態(tài)方法時(即在字節(jié)碼中執(zhí)行invokestatic指令)
    3)當使用某個類或接口的靜態(tài)字段,或者對該字段賦值時(即在字節(jié)碼中執(zhí)行getstatic或putstatic指令時,用final修飾的靜態(tài)字段除外,它被初始化為一個編譯時的常量表達式)
    4)當調用Java API的某些反射方法時,比如類Class中的方法或者java.lang.reflect包中的類的方法
    5)當初始化某個類的子類時(除接口外)
    6)當虛擬機啟動時某個被表明為啟動類(含有main方法)的類
    除以上六種情形外,所有其它使用Java類型的方式都是被動使用,都不會導致Java類型的初始化