URLClassLoader應用

Java虛擬機中定義了一個類裝載器子系統和執行引擎子系統.其中類裝載器子系統主要是負責裝載類二進制文件到JVM中的,而執行引擎子系統則負責執行其中的指令.二者都是虛擬機的具體實現,執行引擎程序代碼中無法控制,相對來說類裝載器就比較靈活.JVM規範中定義虛擬機必須實現啓動類裝載器(bootstarp),但是用戶可以定義自己的類裝載器.一個程序啓動的時候有3個類加載器.

第一個是啓動類加載器,它負責加載Java的核心類.它是JVM實現的一部分,不是ClassLoader的子類.是用C代碼實現的.第二個類加載器是擴展類加載器,它負責加載JDK的擴展類,也就是目錄配置屬性.第三個是APP的類加載器,通常用ClassLoader.getSystemClassLoader()可以獲得,負責加載CLASSPATH下的類.一般這3個類加載器足以滿足我們的應用.雖然假如我們的程序需要加載上述3個加載器不能到達類.那麼我們就只能定義自己的類加載器.

  1. public static void main(String[] args) throws Exception  
  2. {  
  3.     try  
  4.     {  
  5.         Class.forName("org.apache.commons.lang.StringUtils");  
  6.     }  
  7.     catch(Exception e)  
  8.     {  
  9.         e.printStackTrace();  
  10.     }  
  11.   
  12.     File file = new File("D:"+File.separator+"commons-lang-2.5.jar");  
  13.     URL url = file.toURI().toURL();  
  14.     URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url});  
  15.     Class clazz = urlClassLoader.loadClass("org.apache.commons.lang.StringUtils");  
  16.     Method isEmpty = clazz.getMethod("isEmpty", String.class);  
  17.   
  18.     System.out.println(isEmpty.invoke(null,"This is not empty!"));  
  19.     System.out.println(isEmpty.invoke(null,""));  
  20. }  

假設在D盤放置了一個apache的commons-lang包,想調用其中的方法,但是我們沒有把他引入到classpath.所以在上述的3個ClassLoader中根本就找不到該類的存在.如上述代碼用Class.forName方法加載類,此時使用的是AppClassLoader,它的上層ClassLoader也沒有該類的引用.所以自然會報出java.lang.ClassNotFoundException的異常出來.所以我們必須定義自己的ClassLoader去加載它,這時候URLClassLoader 就派上用場了.它接受一個URL數組爲參數,代表的意義是它可以在提供的路徑中加載到提供的類.於是上述代碼就可以使用loadClass來加載返回一個Class對象.然後用java反射來調用加載的類的方法.上述代碼是調用了org.apache.commons.lang.StringUtils的靜態方法isEmpty.

在WEB容器的實現中也用了此方法.有興趣的話可以參考下Tomcat的源碼.容器啓動的時候Bootstrap在設置完基本的目錄之後,第一件事就是先調用initClassLoaders來構造自己的類加載器層次.

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