類加載

1、JVM類加載機制java

  (1)類加載時機數組

    下圖是類的生命週期。數據結構

    

    其中 加載、驗證、準備、初始化和卸載這5個階段的順序是肯定的,而解析階段則不必定,它在某些狀況下能夠   在初始化以後再開始,這是爲了支持JAVA語言的運行時綁定。多線程

    初始化階段:有且只有5中狀況下必須當即對類進行初始化佈局

    1)new 一個對象(new一個對象數組時是不會進行初始化操做的),讀取或設置類的靜態字段,調用類的靜態方法。
spa

    2)反射調用的時候,若是類沒有初始化,則須要先觸發初始化.net

    3)當初始化一個類時,若是發現父類沒有被初始化,則須要先初始化父類線程

    4)當虛擬機啓動的時候,main()方法所在的主類會被先初始化翻譯

    5)當使用JDK1.7的動態語言支持時指針

2、類加載過程

    加載:

    1. 經過一個類的全限定名來獲取此類的二進制字節流(例如class文件)。
    2. 將這個字節流所表明的的靜態存儲結構轉換爲方法區的運行時數據結構。
    3. 在內存中生成表明這個的類的java.lang.Class對象,做爲方法區中這個類各類數據的訪問入口

    驗證:

      舉例:將一個對象轉換爲它並未實現的類型,若是這樣作了,編譯器拒絕編譯

    準備:

      正式爲靜態變量分配內存並設置類變量初始值,這些變量所使用的內存都在方法區中進行分配

      一般狀況下初始值是以下表所示:

      

      若是靜態變量是final類型的,即字段屬性表中存在ConstantValue屬性,那麼在準備階段就會被初始化爲ConstantValue所指定的值。

      例如 public static final int value = 123231;  //value在準備階段直接被賦值爲123231,而不是0。

    解析:將常量池中的符號引用替換爲直接引用的過程  

    1.符號引用(Symbolic References):

    符號引用以一組符號來描述所引用的目標,符號能夠是任何形式的字面量,只要使用時可以無歧義的定位到目標便可。例如,在Class文件中它以CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info等類型的常量出現。符號引用與虛擬機的內存佈局無關,引用的目標並不必定加載到內存中。在Java中,一個java類將會編譯成一個class文件。在編譯時,java類並不知道所引用的類的實際地址,所以只能使用符號引用來代替。好比org.simple.People類引用了org.simple.Language類,在編譯時People類並不知道Language類的實際內存地址,所以只能使用符號org.simple.Language(假設是這個,固然實際中是由相似於CONSTANT_Class_info的常量來表示的)來表示Language類的地址。各類虛擬機實現的內存佈局可能有所不一樣,可是它們能接受的符號引用都是一致的,由於符號引用的字面量形式明肯定義在Java虛擬機規範的Class文件格式中。

 
    2.直接引用:
 直接引用能夠是
(1)直接指向目標的指針(好比,指向「類型」【Class對象】、類變量、類方法的直接引用多是指向方法區的指針)
(2)相對偏移量(好比,指向實例變量、實例方法的直接引用都是偏移量)
(3)一個能間接定位到目標的句柄
直接引用是和虛擬機的佈局相關的,同一個符號引用在不一樣的虛擬機實例上翻譯出來的直接引用通常不會相同。若是有了直接引用,那引用的目標一定已經被加載入內存中了。
     初始化:
     類初始化階段是類加載過程的最後一步, 到了初始化階段,才真正開始執行類中的定義的java代碼。
    初始化階段是執行類構造器<clinit>()方法的過程。clint()方法是由編譯器自動收集全部靜態變量的賦值動做和靜態語句塊(static{})中的語句合併而成的,
      • 編譯器的收集順序是由語句在源文件中出現的順序決定。
      • 父類的clint方法會先執行,也就意味着父類的靜態語句塊要優先於子類的靜態變量賦值操做。
      • 虛擬機會保證一個類的clinit方法在多線程中被正確的加鎖,同步。

3、類加載器

相關文章
相關標籤/搜索