Java類加載的過程

前言

Java的類的生命周期為:加載、驗證、準備、解析、初始化、使用、卸載七個生命周期。其中,加載、驗證、準備、解析、初始化可以稱之為類的加載過程,而加載和類加載過程是有區(qū)別的,它只是類加載過程的一個階段。


image

類加載的過程

加載

這個階段主要完成三件事情:

1)通過一個類的全限定類名來獲取描述此類的二進制字節(jié)流。

2)將這個字節(jié)流代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)運行時的數(shù)據(jù)結(jié)構(gòu)。

3)在內(nèi)存中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)這個類的各種數(shù)據(jù)的訪問入口。

類加載完成后,虛擬機外部的二進制字節(jié)流就按照虛擬機所需的格式存儲在方法區(qū)中,然后再內(nèi)存中實例化一個java.lang.Class對象(對于HotSpot虛擬機而言,class對象不存在于Java堆,而在方法區(qū)中創(chuàng)建),這個對象將作為外部程序訪問方法區(qū)中這些類型數(shù)據(jù)的外部接口。

驗證

這一階段的目的主要是確保class文件的字節(jié)流中所包含的信息符合虛擬機規(guī)范的要求,并且不會危害虛擬機,確保虛擬機自身安全。

主要進行四部分的驗證:

1)文件格式的驗證,class文件是否符合虛擬機class文件格式規(guī)范,比如是否以0xCAFEBABE開頭、主次版本號是否和當前虛擬機匹配,等等。

2)元數(shù)據(jù)驗證,主要對字節(jié)碼描述的信息進行語義分析,確保語言描述符合java語言規(guī)范,如是否繼承了被final修飾的類等等。

3)字節(jié)碼驗證,主要是通過數(shù)據(jù)流和控制流分析,確保程序語義是合法的、符合邏輯的,這一個階段也是最復雜的驗證階段。

4)符號引用驗證,對類自身以外的信息(常量池中的各種符號引用)進行匹配性校驗,通常校驗的內(nèi)容有:

4.1符號引用中通過字符串描述的全限定類名能否找到對應的類。

4.2在指定類中是否存在符合方法的字段描述符以及簡單名稱描述的方法和字段。

4.3符號引用中類、字段、方法的訪問性是否可被當前類訪問。

準備

準備階段是正式為類變量分配內(nèi)存并設置類變量初始值的階段,這些變量所需要的內(nèi)存,都將在方法區(qū)中進行分配。這里有概念容易混淆:第一,這時候進行內(nèi)存分配僅包括類變量(被static修飾的),不包括實例變量,實例變量將隨著對象實例化時一起在Java堆中分配內(nèi)存。第二,這里所說的初始值,通常情況下是數(shù)據(jù)類型的0值或者null值。
比如:public static int value = 123; value在準備階段后的初始值是0而不是123。
如果類變量定義的是一個常量的話,那么在準備階段會將value直接賦值。比如:
public static final int value = 123;,value在準備階段會被賦值為123。

解析

解析階段主要是完成符號引用替換為直接引用。主要包括類或接口的解析、字段解析、類方法解析、接口方法解析。

初始化

初始化階段主要是給類的成員變量進行初始化值,在這個階段,虛擬機會自動創(chuàng)建一個<cinit>方法,我們稱之為類構(gòu)造器,這個方法的要執(zhí)行的內(nèi)容主要包括兩部分,類成員變量的初始化和靜態(tài)代碼塊。它們的執(zhí)行順序按照在類中的定義的順序。其中,靜態(tài)代碼塊中可以對其前面定義的類成員變量賦值和訪問,但不可以對其后定義的類成員變量訪問,但可以賦值。

static {
        i = 2;                      // 給變量賦值可以正常編譯通過
        //System.out.println(i);    // 編譯不通過,會提示"非法向前引用"
    }
static int i = 1;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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

  • JVM規(guī)定,在以下四種情況下必須要對一個類進行初始化操作 實例化了類的對象 通過反射調(diào)用了類的實例化方法 實例化了...
    柳蒿閱讀 219評論 0 1
  • 虛擬機把描述類的數(shù)據(jù)從Class文件加載到內(nèi)存, 并對數(shù)據(jù)進行校驗、轉(zhuǎn)換解析和初始化, 最終形成可以被虛擬機直接使...
    好好學習Sun閱讀 1,379評論 0 3
  • 前言 從一個.class文件變成一段可執(zhí)行的程序,就是類加載的工作。分為三大部分:加載,鏈接,初始化。下面介紹一下...
    傳蔥閱讀 393評論 0 0
  • 代碼編譯的結(jié)果從本地機器碼轉(zhuǎn)變?yōu)樽止?jié)碼,是存儲格式發(fā)展的一小步,確實編譯語言發(fā)展的一大步。 虛擬機把描述類的數(shù)據(jù)從...
    胡二囧閱讀 1,067評論 0 0
  • 1.加載,將二進制字節(jié)流加載到方法區(qū),然后在java堆中實例化一個java.lang.Class類的對象2.驗證:...
    蒸汽飛船閱讀 844評論 0 0

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