JVM 類加載器深刻解析以及重要特性剖析 初始化對於類和接口的異同點深刻解析

一、類加載流程圖html

從磁盤加載到銷燬的完整過程。java

 

二、類加載流程圖2程序員

一、加載: 就是把二進制形式的java類型讀入java虛擬機中數據結構

二、鏈接: 驗證、準備、解析。post

鏈接就是將已經讀入到內存的類的二進制數據和合併到虛擬機的運行時環境中url

  驗證:spa

    類文件的結構檢查操作系統

    語義檢查htm

    字節碼驗證對象

    二進制兼容性驗證

  準備: 爲類分配內存,設置默認值。可是在到達初始化以前,類變量都沒有初始化爲真正的初始值。

  解析:解析過程就是在類型的常量池中尋找類、接口、字段和方法的符號引用,把這些符號引用替換爲直接引用的過程。

三、初始化: 爲類變量賦於真正的初始值

四、類實例化: 

  爲新的對象分配內存

  爲實例變量賦默認值

  爲實例變量賦正確的初始值

  java編譯器爲它編譯的每個類都至少生成一個實例化方法,在java的class文件中,這個實例初始化方法被稱爲「 <init>"。針對源碼中的每個類的構造方法,java編譯器都產生一個<init> 方法。

五、垃圾回收和對象終結

 

三、類的加載

類的加載的最終產品是位於內存中的Class對象

Class對象封裝了類在方法區內的數據結構,而且向Java程序員提供了訪問方法區內的數據結構

 

四、類加載器

有兩種類型的類加載器

1)Java虛擬機自帶的加載器

  根類加載器(Bootstrap)

  擴展類加載器(Extension)

  系統(應用)類加載器(System)

2)用戶自定義的類加載器

  Java.lang.ClassLoader 的子類

  用戶能夠定製類的加載方式

 

五、類加載器並不須要等到某個類被」首次主動使用「時再加載它。

JVM規範容許類加載器在預料某個類將要被使用時就預先加載它,若是在預先加載過程當中遇到了.class 文件缺失或存在錯誤,類加載器必須在程序主動使用該類是才報告錯誤(LinkageError錯誤

若是這個類一直沒有被程序主動適應,那麼類加載器就不會報告錯誤

 

六、類的準備、類的初始化

在準備階段,Java虛擬機爲類的靜態變量分配內存,並設置默認初始值。對於一下Sample類,在準備階段,將爲int類型的靜態變量a分配4個字節的內存空間,而且賦予默認值爲0,爲long類型的靜態變量b分配8個字節的內存空間,而且賦值0.

 

在初始化階段,Java虛擬機執行類的初始化語句,爲類的靜態變量賦予初始值。在程序中,靜態變量的初始化有兩種途徑: (1)在靜態變量聲明處進行初始化 (2)在靜態代碼塊中進行初始化。例以下面Sample類的代碼中,靜態變量a和b都被顯示初始化,而靜態變量c沒有被顯示初始化,它將保持默認值0

 

在初始階段,靜態變量的聲明語句,以及靜態代碼塊都被看做類的初始化語句。Java虛擬機會按照初始化語句在類文件中的前後順序來依次執行它們。例以下面的Sample2類被初始化後,它的靜態變量a的取值爲4.

public class Sample2 {
    static  int a = 1;
    static {
        a = 2;
    }
    static {
        a = 4;
    }

    public static void main(String[] args) {
        System.out.println("a=" + a); //打印a=4
    }
}

  

七、類的初始化步驟

1) 假如這個類沒有被加載和鏈接,那就先進行加載和鏈接

2)假如類存在直接父類,而且這個父類尚未被初始化,那就先初始化直接父類

3)加入類中存在初始化語句,那就依次執行這些初始化語句。

 

八、當Java虛擬機初始化一個類時,要求它的全部父類都已經初始化,可是這條規則不適於接口

1) 當初始化一個類時,並不會先初始化它所實現的類的接口。

2) 在初始化一個接口時,並不會先初始化它的父接口

所以,一個父接口並不會由於它的子接口或者實現類的初始化而初始化。只有當程序首次使用特定接口的鏡頭變量時,纔會致使該接口的初始化。

 代碼Sample 初始化對於類和接口的異同點深刻解析

 

九、類的初始化時機

只有當程序訪問的靜態變量或者靜態方法確實在當前類或當前接口中定義時,才能夠認爲是對類或接口的主動使用。

調用ClassLoader類的loadClass方法加載的一個類,並不會對類的主動使用,不會致使類的初始化。

 

十、Java虛擬機自帶類加載器

1)根類加載器(Bootstrap): 該加載器沒有父加載器,它負責加載虛擬機的核心庫,如java.lang.*等。如java.lang.Object就是根加載器加載的。根加載器從系統屬性sun.boot.class.path 所指定目錄中加載類庫。根加載器的實現依賴於底層操做系統,屬於虛擬機的實現的一部分,它沒有繼承java.lang.ClassLoader類。(C++) 主要加載rt.jar

2)擴展類加載器(Extension)

它的父加載器爲根類加載器。它從java.ext.dirs系統屬性所指定的目錄中加載類庫,或者從JDK的安裝目錄的jre/lib/ext子目錄(擴展目錄)下加載類庫。若是把用戶建立的JAR文件放在這個目錄下,也會自動由擴展類加載器加載。擴展類加載器是純Java類,是Java.lang.ClassLoader的子類。

3)系統(應用)類加載器(System),也稱爲APP ClassLoader extends ClassLoader 應用加載器,它的父加載器爲擴展類加載器。它從環境變量classpath或者系統屬性java.class.path 所指定的目錄中加載類,它是用戶自定義的類加載器的默認父加載器,系統類加載器是純Java類,是java.lang.ClassLoader類的子類。

以下圖:他們之間的關係不是繼承,是包含關係。 如擴展類加載器包含了擴展類加載器。

相關文章
相關標籤/搜索