JVM ClassLoad

有些時候呢,當你對一個東西很熟悉了的時候,當你再重拾起這件東西的時候呢,你就有可能會有對其更深的理解,或者是想去更深的理解。.class文件被類加載器ClassLoader加載到內存,並被表示爲Class對象,被JVM解析執行,那麼,今兒,徹底來了解了解它的工作機制。

  類裝載器ClassLoader呢,就是尋找類或接口字節碼文件(.class)進行解析並構造JVM內部對象表示的組件。類加載的工作由ClassLoader及其子類負責,它並非是一次性的加載多個class文件,需要的時候才才加載進來,這個就是我們常說的運行期間動態加載,如何想看看究竟類的具體加載過程呢,可以用-verbose:class參數,現看例子程序來了解了解ClassLoader何來個運行期動態加載,以後看看具體的加載過程,如下:

 

Java代碼  收藏代碼
  1. public class DynamicLoadClassDemo {  
  2.   
  3.     public static void main(String[] args) {  
  4.         new WaitingToLoadedOneClass();  
  5.         System.out.println("demonstrate dynamic loaded......");  
  6.         new WaitingToLoadedTwoClass();  
  7.     }  
  8.   
  9. }  
  10.   
  11. class WaitingToLoadedOneClass {  
  12.       
  13. }  
  14.   
  15. class WaitingToLoadedTwoClass {  
  16.       
  17. }  

   看這個例子,裏面有三個類,主類爲DynamicLoadClassDemo,在main函數裏,在聲明兩個對象之間有一條打印語句,如果ClassLoader是動態加載類的話,那麼,輸出的語句會在這兩個類的加載中間對吧,爲了能夠看清楚這一過程,我們加上-verbose:class,在MyEclipse編輯窗口中,右擊-->“Run As”-->“Open Run Dialog...”-->“Arguments”-->“VM arguments”,輸入-verbose:class-->“Run”,會把類的加載如實的打印在控制檯上,現截我們敢興趣的運行結果如下:

  

Java代碼  收藏代碼
  1. [Loaded com.cui.hourse.reflectDemo.DynamicLoadClassDemo from file:/G:/workspace/HourseSystem/WebRoot/WEB-INF/classes/]  
  2. [Loaded com.cui.hourse.reflectDemo.WaitingToLoadedOneClass from file:/G:/workspace/HourseSystem/WebRoot/WEB-INF/classes/]  
  3. demonstrate dynamic loaded......  
  4. [Loaded com.cui.hourse.reflectDemo.WaitingToLoadedTwoClass from file:/G:/workspace/HourseSystem/WebRoot/WEB-INF/classes/]  

  完全的動態加載呀,輸出語句,就在兩個聲明對象之間。

  實際上呢,輸的語句不僅僅是這些了,JVM在運行時會產生三個ClassLoader:根裝載器、擴展類裝載器(ExtClassLoader)、系統應用類裝載器(AppClassLoader)。

  現分別對這幾個類的裝載器說明如下:

    1)根裝載器(bootstrap class Loader):計算機本地語言所編寫(彙編、C/C++),加載jre最核心的類,如JRE擴展目標下的rt.jar、charsets.jar...,如java.lang.String類;

    2)擴展類裝載器(extesion class loader):加載jre/lib/ext包裏的jar類,如;

    3)系統應用類裝載器(applicatioin class loader):負責加載classpath路徑下的包類,通常是用戶定義的類,也是系統默認的裝載方式;

  JVM裝載類時使用“全盤負責委託機制”。“全盤負責”是指當一個ClassLoader裝載一個類時,該類所依賴及引用的類也由這個ClassLoader載入,當然了,別指定一ClassLoader除外;“委託機制”是指呢委託父裝載器尋找目標類,只有找不到的情況下,纔會從自己的當前路徑下查找並裝載目標類。就像AppClassLoader-->ExtClassLoader-->根裝載器,這三個裝載器之間存在着父子層級之間的關係,讓我們來做個實驗看看:

 

Java代碼  收藏代碼
  1. //根加載器,因爲非Java語言所寫,所以會返回null  
  2.         System.out.println(String.class.getClassLoader());  
  3.         //jre6\lib\ext包下dnsns.jar裏的類,擴展類加載器加載  
  4.         System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());  
  5.         //系統默認加載方式,應用類加載器,然後獲取它的父加載器,一級一級的往上,分別爲擴展類加載器、根加載器  
  6.         System.out.println(ClassLoader.getSystemClassLoader());  
  7.         System.out.println(ClassLoader.getSystemClassLoader().getParent());  
  8.         System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent());  

   控制檯輸出如下信息:

   

Java代碼  收藏代碼
  1. null  
  2. sun.misc.Launcher$ExtClassLoader@addbf1  
  3. sun.misc.Launcher$AppClassLoader@19821f  
  4. sun.misc.Launcher$ExtClassLoader@addbf1  
  5. null  

   完全與我們想像的一致,這樣,你就理解了,呵呵!

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