版權聲明:本文為部落客原創文章,轉載注明出處http://blog.csdn.net/u013142781
(1)類的生命周期包括了:加載(loading)、驗證(verification)、準備(preparation)、解析(resolution)、初始化(initialization)、使用(using)、解除安裝(unloading)七個階段
(4)驗證階段:驗證是為了確定class檔案的位元組流中包含的資訊符合目前虛拟機的要求,并且不會危害虛拟機自身的安全;包括檔案格式驗證、中繼資料驗證、位元組碼驗證、符号引用驗證;如果驗證到輸入的位元組流不符合class檔案的存儲格式,就抛出一個java.lang.verifyerror異常或其子類異常。
(5)準備階段:準備階段是正式為類變量配置設定記憶體并設定類變量初始值(各資料類型的零值)的階段,這些記憶體将在方法區中進行配置設定。
(6) 解析階段:解析階段是在虛拟機将常量池内的符号引用替換為直接引用的過程。符号引用:符号引用以一組符号來描述所引用的目标,符号可以是任何形式的字面量,隻要使用時能無歧義地定位到目标即可。符号引用與虛拟機實作的記憶體布局無關,引用的目标并不一定已經加載到記憶體中。直接引用:直接引用可以是直接指向目标的指針、相對偏移量或者一個能間接定位到目标的句柄。如果有了直接引用,那引用的目标必定已經在記憶體中存在。
(7)初始化階段:初始化階段是執行類構造器<code><clinit></code>()方法的過程。
初始化是重點,需要清楚以下幾點:
1、<code><clinit></code>()方法是由編譯器自動收集類中的所有類變量的指派動作和靜态語句塊(static{}塊)中的語句合并産生的,編譯器收集的順序是由語句在源檔案中出現的順序決定的。靜态語句塊隻能通路到定義在靜态語句塊之前的變量,定義在它之後的變量,在前面的靜态語句塊中可以指派,但是不能通路。
2、 方法與執行個體構造器<code><cinit></code>()不同,不需要顯示的調用父類構造器,虛拟機會保證在子類的<code><clinit></code>()方法執行之前,父類的<code><clinit></code>()已經執行完畢。
3、<code><clinit></code>()方法對于類或接口來說不是必須的,如果一個類中沒有靜态語句塊也沒有對變量的指派操作,那麼編譯器可以不為這個類生成<code><clinit></code>()方法。
4、 執行接口的<code><clinit></code>()不需要先執行父接口的<code><clinit></code>()方法,隻有當父接口中定義的變量被使用時,父接口才會被初始化。接口的實作類在初始化時也不會執行接口的<code><clinit></code>()方法。
5、虛拟機會保證一個類的<code><clinit></code>()方法在多線程環境中被正确的加鎖和同步,如果多個線程同時去初始化一個類,則隻會有一個線程去執行這個類的<code><clinit></code>()方法,其他線程需要阻塞等待。