類的加載機制 (一)

      做爲的學習筆記,類的加載機制主要從類的加載,連接,以及初始化 ,類加載器除了根類加載器之外,其他類加載器都是用java編寫的,所以我們程序員可以開發自己的類加載器,通過使用自定義類加載器,可以完成一些特定的功能。

  1 jvm 和類的認識

         當我們通過java命令運行java程序時,這個命令就會啓動一個java虛擬機進程,我們的java程序就處於這個進程中,java程序中的所有線程,所有變量都處於jvm的同一個進程裏,它們都使用該jvm進程的內存區。

     當系統出現一下情況時,jvm進程將被終止

      》程序運行到最後正常結束

      》程序所在平臺強制結束了jvm進程

      》 程序執行過程中遇到未捕獲的異常或者錯誤而結束

      》 程序運行到使用System.exit() 或者Runtime.getRuntime().exit()代碼處結束程序

java程序結束,jvm進程結束,該進程在內存中的狀態將會失去,下面舉例子說明:

     &  首先創建一個靜態變量 q  

public class TestQ {
   //定義一個靜態變量
	public static int q = 4;
}

    & 定義一個測試類 創建TestQ實例,並訪問該實例的靜態變量q  

public class TestTQ {
   public static void main(String[] args) {
	 TestQ  t = new TestQ();
	 t.q++;
	 System.out.println(t.q);
    }
}

 & 創建第二測試類 並訪問類變量q

public static void main(String[] args) {
	   TestQ t2 = new TestQ();
	   System.out.println(t2.q);
	}
}

      我們首先運行第一個測試類 訪問q 自增了1  程序給出的結果是5 相信大家對這個結果沒有什麼疑問把,而我們再來運行第二個測試類的結果是多少呢,依然是4 ,爲什麼呢? 原因是兩次運行java程序處於2個不同的jvm進程中,第一次運行jvm結束後,它對q所做的修改將全部失去,兩個jvm之間不會共享數據。

2 類的加載

    類的加載: 當程序主動使用 一個類時 ,如果該類沒有被加載時,則jvm會通過 加載  連接 初始化三個步逐來對類進行初始化操作 ,三個操作一次完成,把這三個步逐統稱爲類加載或類初始化,類加載就是將類的class文件讀入內存,併爲之創建一個java.lang.Class對象 。

     類的加載又類加載器完成的,類加載器通常是由jvm提供,這些類加載器也是程序運行的基礎,類加載器分爲2類,一是jvm提供的系統類加載器,另一個是 開發者可以通過繼承ClassLoader基類來創建自己的類加載器,

      通過使用不同的類加載器。可以從不同來源加載類的二進制數據,通常有如下幾種來源:

     》 從本地系統文件加載class文件

     》從jar包加載class文件

     》通過網絡加載class 文件

     》把一個java 源文件動態編譯,並執行加載

類的加載不一定都是在”第一次使用“ 才進行加載,java虛擬機規範允許系統預先加載一些類。

3 類的連接

      當類被加載了之後,系統會爲之生成一個對應的class對象,接着將會進入連接階段,連接階段負責把類的二進制數據合併到jre中,而類的連接又分爲三個階段

    》 驗證: 驗證階段用於檢測被加載的類是否又正確的內部結構,並且和其他類協調一致

    》 準備 :類準備階段則負責爲類變量分配內存,並設置默認初始值

    》 解析:將類的二進制數據中的符號引用替換成直接引用

4 類的初始化

   虛擬機負責對類進行初始化,主要就是對類變量進行初始化,在java類中對類變量指定初始值有2種方式:1是 聲明變量時指定初始值  2是 使用靜態初始化塊爲類變量指定初始值  靜態初始化塊都將被當成類的初始化語句,jvm會按照這些語句在程序中的排序順序依次執行它們。

public class Test01 {
  static{
	  int b = 8;
	  System.out.println("-------");
  }
     static int a = 3;
     static int b = 12;
     static int c;
     public static void main(String[] args) {
		System.out.println(Test01.b);
		System.out.println(Test01.c);
	}
}

  其中b的值爲12 ,c 的值爲0 ,b在第二次賦值會把其中的值替換掉,沒有賦予值的int 類型,默認值爲0。

    jvm 初始化一個類包含如下幾個步逐

 》 如果這個類還沒有被加載和連接。則程序先加載並且連接該類

 》 如果該類的直接父類還沒有被初始化,則先初始化其直接父類(jvm 最先初始化的總是java.lang.Object類)

 》如果類中有初始化語句,則系統一次執行這些初始化語句

當程序主動使用一個類時,系統會保證該類以及所用父類都會被初始化。

5 類初始化的時機

 》 調用一個類的靜態方法

》訪問一個類或接口的類變量,或爲類變量賦值

 》 使用反射方式來強制創建一個類或者接口對應的java.lang.Class對象 (Class.forName("Person"))

》初始化一個類的子類

》直接使用java.exe命令來運行一主類  程序先初始化主類

 

 

 

   

                                                                                                                                                                                                                                                                                                                                                    

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章