熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

ClassLoader介紹

2013-11-15 11:44:13  來源: JSP教程 

  JVM在運行時會產生三個ClassLoaderBootstrap ClassLoaderExtension ClassLoader和AppClassLoader其中Bootstrap是用C++編寫的我們在Java中看不到它是null它用來加載核心類庫在JVM源代碼中這樣寫道
  static const char classpathFormat[] =
  %/lib/rtjar:
  %/lib/injar:
  %/lib/sunrsasignjar:
  %/lib/jssejar:
  %/lib/jcejar:
  %/lib/charsetsjar:
  %/classes;
  知道為什麼不需要在classpath中加載這些類了吧?人家在JVM啟動的時候就自動加載了並且在運行過程中根本不能修改Bootstrap加載路徑
  Extension ClassLoader用來加載擴展類即/lib/ext中的類
  最後AppClassLoader才是加載Classpath的
  ClassLoader加載類用的是委托模型即先讓Parent類(而不是Super不是繼承關系)尋找Parent找不到才自己找看來ClassLoader還是蠻孝順的三者的關系為:AppClassLoader的Parent是ExtClassLoader而ExtClassLoader的Parent為Bootstrap ClassLoader加載一個類時首先BootStrap先進行尋找找不到再由ExtClassLoader尋找最後才是AppClassLoader
  為什麼要設計的這麼復雜呢?其中一個重要原因就是安全性比如在Applet中如果編寫了一個javalangString類並具有破壞性假如不采用這種委托機制就會將這個具有破壞性的String加載到了用戶機器上導致破壞用戶安全但采用這種委托機制則不會出現這種情況因為要加載javalangString類時系統最終會由Bootstrap進行加載這個具有破壞性的String永遠沒有機會加載
  我們來看這段代碼
  [code]//Ajava
  public class A{
  public static void main(String[] args){
  A a=new A();
  Systemoutprintln(SystemgetProperty(javaextdirs));
  Systemoutprintln(agetClass()getClassLoader());
  B b=new B();
  bprint();
  }
  }
  //Bjava
  public class B{
  public void print(){
  Systemoutprintln(thisgetClass()getClassLoader());
  }
  }[/code]
  
  我們將它放在Classpath中則打印出
  sunmiscLauncher$AppClassLoader@ec
  sunmiscLauncher$AppClassLoader@ec
  可見都是由AppClassLoader來加載的
  我們將其放在%jre%/lib/ext/classes(即ExtClassLoader的加載目錄其加載/lib/ext中的jar文件或者子目錄classes中的class文件)中則會打印出
  sunmiscLauncher$ExtClassLoader
  sunmiscLauncher$ExtClassLoader
  我們將Aclass放到%jre%/lib/ext/classes中而將Bclass放到classpaht中又會怎麼樣呢?結果是
  sunmiscLauncher$ExtClassLoader
  Exception in thread main javalangNoClassDefFoundError:B
  at Amain(Ajava:)
  
  怎麼會這樣呢?這其中有一個重要的問題A類當然是由ExtClassLoader來加載的B類要由哪個加載呢?B類要由調用它自己的類的類加載器(真拗口)也就是說A調用了B所以B由A的類加載器ExtClassLoader來加載ExtClassLoader根據委托機制先拜托Bootstrap加載Bootstrap沒有找到然後它再自己尋找B類還是沒找到所以拋出異常ExtClassLoader不會請求AppClassLoader來加載!你可能會想這算什麼問題我把兩個類放到一起不就行了?
  
  呵呵沒這麼簡單比如JDBC是核心類庫而各個數據庫的JDBC驅動則是擴展類庫或在classpath中定義的所以JDBC由Bootstrap ClassLoader加載而驅動要由AppClassLoader加載等等問題來了Bootstrap不會請求AppClassLoader加載類啊那麼他們怎麼實現的呢?我就涉及到一個Context ClassLoader的問題調用ThreadgetContextClassLoader
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19529.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.