day43-反射02( 四 )


文章插圖
虛擬機將常量池內的符號引用替換為直接應用的過程

個人理解 java虛擬機中的符號引用和直接引用_maerdym的博客-CSDN博客
6.1.5初始化階段
day43-反射02

文章插圖
  1. 到初始化階段 , 才真正開始執行類中定義的Java程序代碼 , 此階段是執行<clinit>()方法的過程
  2. <clinit>()方法是 由編譯器按語句在源文件中出現的順序,依次自動收集類中的所有靜態變量 的賦值動作和靜態代碼塊中的語句,并進行合并 。-->例子1
  3. 虛擬機會保證一個類的<clinit>()方法在多線程環境中被正確地加鎖、同步,如果多線程同時去初始化一個類,那么只會有一個線程去執行這個類的<clinit>()方法,其他線程都需要阻塞等待,直到活動線程執行<clinit>()方法完畢 。
例子1:演示類加載的初始化階段
package li.reflection.classload_;//演示類加載的初始化階段public class ClassLoad03 {public static void main(String[] args) {//分析:/*** 1.加載B類,并生成 B的Class對象* 2.鏈接 :將num默認初始化為 0* 3.初始化階段:*3.1依次 自動收集類中的 所有靜態變量的賦值動作 和 靜態代碼塊中的語句,并合并*收集:*clinit(){*System.out.println("B的靜態代碼塊被執行");*num = 300;*num = 100;*}*合并:num =100;*///直接使用類的靜態屬性也會導致類的加載System.out.println(B.num);//100}}class B {static {System.out.println("B的靜態代碼塊被執行");num = 300;}static int num = 100;public B() {System.out.println("B的構造器被執行");}}
day43-反射02

文章插圖
例子2:
在例子1中的程序里創建一個B類對象 , 打上斷點,debug源碼:
day43-反射02

文章插圖
可以看到在底層中,使用了對象鎖synchronized (getClassLoadingLock(name)) :
day43-反射02

文章插圖
也就是說,加載類的時候 , 是有類的同步控制機制 。
正因為有這個機制,才能保證某個類在內存中 , 只有一份Class對象 。

推薦閱讀