JVM類加載過程

類加載和初始化只進行一次java

1,加載(須要類加載器的支持):這個階段會在內存中生成一個表明這個類的java.lang.Class對象,做爲方法區這個類的各類數據的入口。注意這裏不必定非得要從一個Class文件獲取,這裏既能夠從ZIP包中讀取(好比從jar包和war包中讀取),也能夠在運行時計算生成(動態代理),也能夠由其它文件生成(好比將JSP文件轉換成對應的Class類)。程序員

2,驗證:這一階段的主要目的是爲了確保Class文件的字節流中包含的信息是否符合當前虛擬機的要求,而且不會危害虛擬機自身的安全。數組

3,準備(都是默認值):準備階段是正式爲類變量分配內存並設置類變量初始值(一般狀況下是數據類型的零值)的階段,這些變量所使用的內存都將在方法區中進行分配。這時候進行內存分配的僅包括類變量(被static修飾的變量),而不包括實例變量,實例變量將會在對象實例化的時候隨着對象一塊兒分配在Java堆中。安全

 

4,解析:解析階段是虛擬機將常量池內的符號引用替換爲直接引用的過程。數據結構

5.初始化:執行類構造器clinit()方法的過程,這個方法是由編譯器自動收集類中全部的類變量的賦值動做和靜態語句塊中的語句合併而成多線程

類初始化階段是類加載過程的最後一步,到了這個階段才真正開始執行類中定義的Java程序代碼(或者說是字節碼)。在準備階段,變量已經賦過一次系統要求的初始值,而在初始化階段,則根據程序員經過程序制定的主觀計劃去初始化類變量和其餘資源。 spa

注意如下幾點:線程

 1.編譯器收集的順序是由語句在源文件中出現的順序決定的,代理

靜態語句塊中只能訪問到定義在靜態語句塊以前的變量,而定義在它以後的變量,在前面的靜態語句塊能夠賦值,但不能訪問,代碼解釋以下:code

public class Test{ static{ i=0;//給變量賦值能夠編譯經過
  sout(i);//編譯器會提示非法向前引用
 }  static int i = 1; }

 

 

2.初始化方法執行的順序,虛擬機會保證在子類的初始化方法執行以前,父類的初始化方法已經執行完畢,

3.虛擬機會保證一個類的clinit()方法在多線程環境中被正確加鎖和同步

4.當訪問一個java類的靜態域時,只有真正聲明這個域的類纔會被初始化

 

 

類的主動引用(會發生初始化)

  • new一個類的對象
  • 調用類的靜態成員(除了final常量)和靜態方法
  • 反射調用時
  • 啓動main方法所在的類
  • 虛擬機會保證在子類的初始化方法執行以前,父類的初始化方法已經執行完畢,

類的被動引用(不會發生初始化)

  • 引用常量不會引起類的初始化:常量在編譯階段就存入調用類的常量池中
  • 經過數組進行類引用,不會觸發初始化
  • 訪問一個靜態域(靜態變量)時,只有真正聲明這個域的類纔會被初始化(子類)

 

 

類加載器:

1.做用:將字節碼文件加載到內存中,將靜態數據轉成方法區運行時數據結構,在堆中生成一個Class類對象,做爲方法區類數據的方法的訪問入口

層次結構(樹狀結構)

 

2.ClassLoader相關方法:

3,類加載器的代理模式

雙親委託機制

相關文章
相關標籤/搜索