The NoteBook of EricKong

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

                JVM在運行時會產(chǎn)生三個ClassLoader,Bootstrap ClassLoaderExtension ClassLoaderAppClassLoader.其中,Bootstrap是用C++編寫的,我們在Java中看不到它,是null。它用來加載核心類庫,在JVM源代碼中這樣寫道:
          static const char classpathFormat[] =
          "%/lib/rt.jar:"
          "%/lib/i18n.jar:"
          "%/lib/sunrsasign.jar:"
          "%/lib/jsse.jar:"
          "%/lib/jce.jar:"
          "%/lib/charsets.jar:"
          "%/classes";
                知道為什么不需要在classpath中加載這些類了吧?人家在JVM啟動的時候就自動加載了,并且在運行過程中根本不能修改Bootstrap加載路徑。Extension ClassLoader用來加載擴展類,即/lib/ext中的類。最后AppClassLoader才是加載Classpath的。
                ClassLoader加載類用的是委托模型。即先讓Parent類(而不是Super,不是繼承關(guān)系)尋找,Parent找不到才自己找。看來ClassLoader還是蠻孝順的。三者的關(guān)系為:AppClassLoader的Parent是ExtClassLoader,而ExtClassLoader的Parent為Bootstrap ClassLoader。加載一個類時,首先BootStrap先進行尋找,找不到再由ExtClassLoader尋找,最后才是AppClassLoader。
               為什么要設(shè)計的這么復(fù)雜呢?其中一個重要原因就是安全性。比如在Applet中,如果編寫了一個java.lang.String類并具有破壞性。假如不采用這種委托機制,就會將這個具有破壞性的String加載到了用戶機器上,導(dǎo)致破壞用戶安全。但采用這種委托機制則不會出現(xiàn)這種情況。因為要加載java.lang.String類時,系統(tǒng)最終會由Bootstrap進行加載,這個具有破壞性的String永遠(yuǎn)沒有機會加載。
          我們來看這段代碼:

          //A.java
          public class A{
              
          public static void main(String[] args){
                  A a
          =new A();
                  System.out.println(System.getProperty(
          "java.ext.dirs"));
                  System.out.println(a.getClass().getClassLoader());
                  B b
          =new B();
                  b.print();
              }

          }

          //B.java
          public class B{
              
          public void print(){
                  System.out.println(
          this.getClass().getClassLoader());
              }

          }

          1、我們將它放在Classpath中,則打印出
          sun.misc.Launcher$AppClassLoader@92e78c
          sun.misc.Launcher$AppClassLoader@92e78c
          可見都是由AppClassLoader來加載的。
          2
          、我們將其放在%jre%/lib/ext/classes(ExtClassLoader的加載目錄。其加載/lib/ext中的jar文件或者子目錄classes中的class文件)中。則會打印出:
          sun.misc.Launcher$ExtClassLoader
          sun.misc.Launcher$ExtClassLoader
          3
          、我們將A.class放到%jre%/lib/ext/classes中,而將B.class放到classpaht中又會怎么樣呢?結(jié)果是:
          sun.misc.Launcher$ExtClassLoader
          Exception in thread "main" java.lang.NoClassDefFoundError:B
              at A.main(A.java:6)
          怎么會這樣呢?這其中有一個重要的問題:A類當(dāng)然是由ExtClassLoader來加載的,B類要由哪個加載呢?B類要由調(diào)用它自己的類的類加載器(真拗口)。也就是說,A調(diào)用了B,所以BA的類加載器ExtClassLoader來加載。ExtClassLoader根據(jù)委托機制,先拜托Bootstrap加載,Bootstrap沒有找到。然后它再自己尋找B類,還是沒找到,所以拋出異常。ExtClassLoader不會請求AppClassLoader來加載!你可能會想:這算什么問題,我把兩個類放到一起不就行了?
              呵呵,沒這么簡單。比如JDBC是核心類庫,而各個數(shù)據(jù)庫的JDBC驅(qū)動則是擴展類庫或在classpath中定義的。所以JDBCBootstrap ClassLoader加載,而驅(qū)動要由AppClassLoader加載。等等,問題來了,Bootstrap不會請求AppClassLoader加載類啊。那么,他們怎么實現(xiàn)的呢?我就涉及到一個Context ClassLoader的問題,調(diào)用Thread.getContextClassLoader

          1 - Tomcat的類載入器的結(jié)構(gòu)

          Tomcat Server在啟動的時候?qū)?gòu)造一個ClassLoader樹,以保證模塊的類庫是私有的
          Tomcat Server的ClassLoader結(jié)構(gòu)如下:

                  +-----------------------------+
                  |         Bootstrap           |
                  |             |               |
                  |          System             |
                  |             |               |
                  |          Common             |
                  |         /      \            |
                  |     Catalina Shared        |
                  |               /    \        |
                  |          WebApp1 WebApp2   |
                  +-----------------------------+

          其中:
          - Bootstrap -
          載入JVM自帶的類和$JAVA_HOME/jre/lib/ext/*.jar
          - System     -
          載入$CLASSPATH/*.class
          - Common   -
          載入$CATALINA_HOME/common/...,它們對TOMCAT和所有的WEB APP都可見
          - Catalina    -
          載入$CATALINA_HOME/server/...,  它們僅對TOMCAT可見,對所有的WEB APP都不可見
          - Shared      -
          載入$CATALINA_HOME/shared/..., 它們僅對所有WEB APP可見,對TOMCAT不可見(也不必見)
          - WebApp    - 
          載入ContextBase/WEB-INF/...,    它們僅對該WEB APP可見

           
          2 - ClassLoader的工作原理 
                每個運行中的線程都有一個成員contextClassLoader,用來在運行時動態(tài)地載入其它類系統(tǒng)默認(rèn)的contextClassLoader是systemClassLoader,所以一般而言java程序在執(zhí)行時可以使用JVM自帶的類、$JAVA_HOME/jre/lib/ext/中的類和$CLASSPATH/中的類可以使用Thread.currentThread().setContextClassLoader(...);更改當(dāng)前線程的contextClassLoader,來改變其載入類的行為ClassLoader被組織成樹形,一般的工作原理是:
          1) 線程需要用到某個類,于是contextClassLoader被請求來載入該類
          2) contextClassLoader請求它的父ClassLoader來完成該載入請求
          3) 如果父ClassLoader無法載入類,則contextClassLoader試圖自己來載入
              注意:WebApp ClassLoader的工作原理和上述有少許不同:
              它先試圖自己載入類(在ContextBase/WEB-INF/...中載入類),如果無法載入,再請求父ClassLoader完成
          由此可得:
              - 對于WEB APP線程,它的contextClassLoader是WebApp ClassLoader
              - 對于Tomcat Server線程,它的contextClassLoader是CatalinaClassLoader


          3 - 部分原代碼分析
           
          3.1 - org/apache/catalina/startup/Bootstrap.java
          Tomcat Server線程的起點
          構(gòu)造ClassLoader樹,并設(shè)置Tomcat Server線程的contextClassLoader為catalinaloader
          載入若干類,然后轉(zhuǎn)入org.apache.catalina.startup.Catalina類中
          package org.apache.catalina.startup;

           

          // JDK類庫
          import java.io.File;
          import java.io.IOException;
          import java.lang.reflect.Method;
          import java.net.MalformedURLException;
          import java.net.URL;
          import java.util.ArrayList;

          //apache自己的類庫
          import org.apache.catalina.loader.Extension;
          import org.apache.catalina.loader.StandardClassLoader;



          /**
           * Boostrap loader for Catalina.  This application constructs a class loader
           * for use in loading the Catalina internal classes (by accumulating all of the
           * JAR files found in the "server" directory under "catalina.home"), and
           * starts the regular execution of the container.  The purpose of this
           * roundabout approach is to keep the Catalina internal classes (and any
           * other classes they depend on, such as an XML parser) out of the system
           * class path and therefore not visible to application level classes.
           *
           * 
          @author Craig R. McClanahan
           * 
          @version $Revision: 1.36 $ $Date: 2002/04/01 19:51:31 $
           
          */


          /**
           * 該類的main方法的主要任務(wù):
           * --------------------------
           *
           * 1,創(chuàng)建TOMCAT自己的類載入器(ClassLoader)
           *      +---------------------------+
           *      |         Bootstrap         |
           *      |             |             |
           *      |          System           |
           *      |             |             |
           *      |          Common           |
           *      |         /      \          |
           *      |     Catalina  Shared      |
           *      +---------------------------+
           *    其中:
           *    - Bootstrap - 載入JVM自帶的類和$JAVA_HOME/jre/lib/ext/*.jar
           *    - System    - 載入$CLASSPATH/*.class
           *    - Common    - 載入$CATALINA_HOME/common/,它們對TOMCAT和所有的WEB APP都可見
           *    - Catalina  - 載入$CATALINA_HOME/server/,它們僅對TOMCAT可見,對所有的WEB APP都不可見
           *    - Shared    - 載入$CATALINA_HOME/shared/,它們僅對所有WEB APP可見,對TOMCAT不可見(也不必見)
           *    注意:當(dāng)一個ClassLoader被請求載入一個類時,它首先請求其父ClassLoader完成載入,
           *    僅當(dāng)其父ClassLoader無法載入該類時,才試圖自己載入該類
           * 2,改變本身線程的默認(rèn)ClassLoader(本線程就是Tomcat Server線程,類載入器是catalinaLoader)
           * 3,讓catalinaLoader載入一些類,類的位置在$CATALINA_HOME/server/lib/catalina.jar中
           * 4,創(chuàng)建org.apache.catalina.startup.Catalina類的一個實例startupInstance,并為其調(diào)用方法:
           *    startupInstance.setParentClassLoader(sharedLoader);
           *    startupInstance.process(args);
           *
           *
           * 有關(guān)ClassLoader的說明:
           * -----------------------
           *
           * 每個被DEPLOY的WEB APP都會被創(chuàng)建一個ClassLoader,用來載入該WEB APP自己的類
           * 這些類的位置是webappX/WEB-INF/classes/*.class和webappX/WEB-INF/lib/*.jar
           *
           * ClassLoader的工作流程是:
           * 1) 收到一個載入類的的請求
           * 2) 請求其父ClassLoader來完成該類的載入
           * 3) 如果父ClassLoader無法載入,則自己試圖完成該類的載入
           *
           * 特別注意WEB APP自己的ClassLoader的實現(xiàn)與眾不同:
           * 它先試圖從WEB APP自己的目錄里載入,如果失敗則請求父ClassLoader的代理
           * 這樣可以讓不同的WEB APP之間的類載入互不干擾
           *
           * WEB APP的ClassLoader的層次結(jié)構(gòu)是:
           *     +----------------------------+
           *     |       Shared               |
           *     |      /      \           |
           *     |   Webapp1  Webapp2      |
           *     +----------------------------+
           * 故對于一個WEB APP,其類載入的優(yōu)先順序如下:
           * - /WEB-INF/classes/*.class 和 /WEB-INF/lib/*.jar
           * - Bootstrap classes of JVM
           * - System class loader classes
           * - $CATALINA_HOME/common/
           * - $CATALINA_HOME/shared/
           *
           *
           * 小結(jié):
           * ------
           *
           * 綜上分析
           * - Tomcat Server線程使用的classLoader是Catalina
           * - 每個WEB APP線程使用的classloader是Webapp?
           *
           
          */



          public final class Bootstrap {
              
          /**
               * DEBUG級別
               
          */

              
          private static int debug = 0;
              
          /**
               * 腳本執(zhí)行該程序時,提供以下的系統(tǒng)屬性:
               * java.endorsed.dirs="$JAVA_ENDORSED_DIRS" -classpath "$CLASSPATH" \
               * java.security.manager \
               * java.security.policy=="$CATALINA_BASE"/conf/catalina.policy \
               * catalina.base="$CATALINA_BASE" \
               * catalina.home="$CATALINA_HOME" \
               * java.io.tmpdir="$CATALINA_TMPDIR" \
               *
               * 
          @param args Command line arguments to be processed
               
          */

              
          public static void main(String args[]) {
                  
          // 設(shè)置debug
                  for (int i = 0; i < args.length; i++)  {
                      
          if ("-debug".equals(args[i]))
                          debug 
          = 1;
                  }

                  
          // 設(shè)置好系統(tǒng)屬性catalina.base,即保證其有值
                  if (System.getProperty("catalina.base"== null)
                      System.setProperty(
          "catalina.base", getCatalinaHome());
                  
          // 創(chuàng)建三個ClassLoader
                  
          // 這三個對象是通過ClassLoaderFactory的靜態(tài)方法創(chuàng)建的
                  
          // 其實際類型是StandardClassLoader,完成tomcat自定義的類載入
                  
          // 這些類對非tomcat及其上的webapp的其它java程序不可見,故用自己的Classloader載入
                  ClassLoader commonLoader = null;
                  ClassLoader catalinaLoader 
          = null;
                  ClassLoader sharedLoader 
          = null;
                  
          try {
                      File unpacked[] 
          = new File[1];
                      File packed[] 
          = new File[1];
                      File packed2[] 
          = new File[2];    
                      ClassLoaderFactory.setDebug(debug);


                      
          // $CATALINA_HOME/common/classes/*.class - 未壓縮的類
                      
          // $CATALINA_HOME/common/endorsed/*.jar - 壓縮的類(endorse:支持)
                      
          // $CATALINA_HOME/common/lib/*.jar - 壓縮的類
                      
          // 這些類是被tomcat server以及所有的webapp所共享的類,由commonLoader負(fù)責(zé)載入

                      unpacked[
          0= new File(getCatalinaHome(),"common" + File.separator + "classes");
                      packed2[
          0=  new File(getCatalinaHome(),"common" + File.separator + "endorsed");
                      packed2[
          1=  new File(getCatalinaHome(),"common" + File.separator + "lib");
                      commonLoader 
          = ClassLoaderFactory.createClassLoader(unpacked, packed2, null);

                      
          // $CATALINA_HOME/server/classes/*.class
                      
          // $CATALINA_HOME/server/lib/*.jar
                      
          // 這些類是僅被tomcat server使用而對webapp不可見的類,由catalinaLoader負(fù)責(zé)載入

                      unpacked[
          0= new File(getCatalinaHome(),"server" + File.separator + "classes");
                      packed[
          0]     = new File(getCatalinaHome(),"server" + File.separator + "lib");
                      catalinaLoader 
          = ClassLoaderFactory.createClassLoader(unpacked, packed,commonLoader);
           
                      
          // $CATALINA_BASE/shared/classes/*.class
                      
          // $CATALINA_BASE/shared/lib/*.jar
                      
          // 這些類是僅被tomcat的webapp使用的類,由sharedLoader負(fù)責(zé)載入

                      unpacked[
          0]  = new File(getCatalinaBase(),"shared" + File.separator + "classes");
                      packed[
          0]      = new File(getCatalinaBase(),"shared" + File.separator + "lib");
                      sharedLoader 
          = ClassLoaderFactory.createClassLoader(unpacked, packed,commonLoader);
                                                               
                      
          // 注意三個自己定置的ClassLoader的層次關(guān)系:
                      
          // systemClassLoader (root)
                      
          //   +--- commonLoader
                      
          //          +--- catalinaLoader
                      
          //          +--- sharedLoader

                              }
           catch (Throwable t) {
                      log(
          "Class loader creation threw exception", t);
                      System.exit(
          1);

                  }


                  
          // 為當(dāng)前的線程更改其contextClassLoader
                  
          // 一般的線程默認(rèn)的contextClassLoader是系統(tǒng)的ClassLoader(所有其它自定義ClassLoader的父親)
                  
          // 當(dāng)該線程需要載入類時,將使用自己的contextClassLoader來尋找并載入類
                  
          // 更改contextClassLoader可以更改該線程的尋找和載入類的行為,但不影響到其它線程
                  
          // 注意!Tomcat Server線程使用的是catalinaLoader

                  Thread.currentThread().setContextClassLoader(catalinaLoader);

                  
          // Load our startup class and call its process() method

                  
          try {
                      
          // 預(yù)載入catalinalLoader的一些類
                      SecurityClassLoad.securityClassLoad(catalinaLoader);
                      
          // 獲得tomcat的啟動類:org.apache.catalina.startup.Catalina,并創(chuàng)建該類的一個實例
                      if (debug >= 1)
                          log(
          "Loading startup class");
                      Class startupClass 
          = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
                      Object startupInstance 
          = startupClass.newInstance();


                      
          // 設(shè)置startupInstance的父ClassLoader,相當(dāng)于執(zhí)行:
                      
          // Catalina startupInstance = new Catailina();
                      
          // startupInstance.setParentClassLoader(sharedLoader);
                      
          // 詳情參考類org.apache.catalina.startup.Catalina

                      
          if (debug >= 1)log("Setting startup class properties");
                      String methodName 
          = "setParentClassLoader";
                      Class paramTypes[] 
          = new Class[1];
                      paramTypes[
          0= Class.forName("java.lang.ClassLoader");
                      Object paramValues[] 
          = new Object[1];
                      paramValues[
          0= sharedLoader;
                      Method method 
          =startupInstance.getClass().getMethod(methodName, paramTypes);
                      method.invoke(startupInstance, paramValues);


                      
          // 使用main方法獲得的參數(shù)args來執(zhí)行process方法,相當(dāng)于:
                      
          // startupInstance.process(args);
                      
          // 詳情參考類org.apache.catalina.startup.Catalina

                      
          if (debug >= 1)log("Calling startup class process() method");
                      methodName 
          = "process";
                      paramTypes 
          = new Class[1];
                      paramTypes[
          0= args.getClass();
                      paramValues 
          = new Object[1];
                      paramValues[
          0= args;
                      method 
          =startupInstance.getClass().getMethod(methodName, paramTypes);
                      method.invoke(startupInstance, paramValues);

                      }
           catch (Exception e) {
                      System.out.println(
          "Exception during startup processing");
                      e.printStackTrace(System.out);
                      System.exit(
          2);
                           }


              }


              
          /**
               * 返回$CATALINA_HOME變量。如果該變量沒有定義,則將之賦值為用戶的當(dāng)前工作目錄。
               
          */

              
          private static String getCatalinaHome() {
                  
          return System.getProperty("catalina.home",System.getProperty("user.dir"));
              }

           
              
          /**
               * 返回$CATALINA_BASE變量。如果該變量沒有定義,則將之賦值為$CATALINA_HOME。
               
          */

              
          private static String getCatalinaBase() {
                  
          return System.getProperty("catalina.base", getCatalinaHome());
              }


              
          /**
               * 輸出LOG信息。
               
          */

              
          private static void log(String message) {
                  System.out.print(
          "Bootstrap: ");
                  System.out.println(message);
              }


              
          /**
               * 輸出由異常引起的LOG信息。
               
          */

              
          private static void log(String message, Throwable exception) {
                  log(message);
                  exception.printStackTrace(System.out);

              }

          }

          3.2 - org/apache/catalina/startup/ClassLoaderFactory.java
          根據(jù)設(shè)置創(chuàng)建并返回StandardClassLoader的實例

           


          package org.apache.catalina.startup;

          import java.io.File;
          import java.io.IOException;
          import java.net.URL;
          import java.util.ArrayList;
          import java.util.jar.JarEntry;
          import java.util.jar.JarFile;

          import org.apache.catalina.loader.StandardClassLoader;


          /**
          * Utility class for building class loaders for Catalina.The factory
          * method requires the following parameters in order to build a new class
          * loader (with suitable defaults in all cases):
          *    A set of directories containing unpacked classes (and resources)
          *         that should be included in the class loader's
          *         repositories.
          *     
          *    A set of directories containing classes and resources in JAR files.
          *         Each readable JAR file discovered in these directories will be
          *         added to the class loader's repositories.
          *     
          *    ClassLoader instance that should become the parent of the new class loader.
          *     
          *
          @author Craig R. McClanahan
          @version $Revision: 1.8 $ $Date: 2002/02/17 08:26:02 $
          */



          public final class ClassLoaderFactory {
             
          /**
               * Debugging detail level for processing the startup.
              
          */

              
          private static int debug = 0;
              
          /**
               * Return the debugging detail level.
               
          */


              
          public static int getDebug() {
                  
          return (debug);
              }

              
          /**
               * 設(shè)置DEBUG級別
               
          */

              
          public static void setDebug(int newDebug) {
                  debug 
          = newDebug;
              }


              
          /**
               * 該類是一個靜態(tài)類,用來創(chuàng)建和返回ClassLoader對象(實際上是StandardClassLoader對象)
               * 它將根據(jù)設(shè)置和參數(shù)返回apache定置的ClassLoader對象,以完成自己的類載入
               *
               * 
          @param unpacked 類路徑CLASSPATH的數(shù)組
               * 
          @param packed 含有JAR文件的類路徑
               * 
          @param parent 父ClassLoader對象。當(dāng)一個ClassLoader對象無法完成類載入時,它將請求父對象幫助
               *
               * 
          @exception Exception if an error occurs constructing the class loader
               
          */


              
          public static ClassLoader createClassLoader(File unpacked[],File packed[], ClassLoader parent)
                  
          throws Exception {
                  
          if (debug >= 1)log("Creating new class loader");
                  
          // list里將被填入所有需要附加到CLASSPATH上去的文件名
                  ArrayList list = new ArrayList();
                  
          // Add unpacked directories
                  if (unpacked != null{
                      
          for (int i = 0; i < unpacked.length; i++)  {
                          File file 
          = unpacked[i];
                          
          if (!file.isDirectory() || !file.exists() || !file.canRead())continue;
                          
          if (debug >= 1)log("  Including directory " + file.getAbsolutePath());
                          URL url 
          = new URL("file"null,file.getCanonicalPath() + File.separator);
                          list.add(url.toString());
                      }

                  }

                  
          // Add packed directory JAR files
                  if (packed != null{
                      
          for (int i = 0; i < packed.length; i++{
                          File directory 
          = packed[i];
                          
          if (!directory.isDirectory() || !directory.exists() ||!directory.canRead()) continue;
                          String filenames[] 
          = directory.list();
                          
          for (int j = 0; j < filenames.length; j++{
                              String filename 
          = filenames[j].toLowerCase();
                              
          if (!filename.endsWith(".jar"))continue;
                              File file 
          = new File(directory, filenames[j]);
                              
          if (debug >= 1)log("  Including jar file " + file.getAbsolutePath());
                              URL url 
          = new URL("file"null,file.getCanonicalPath());
                              list.add(url.toString());
                          }

                      }

                  }

                  
          // 填好了list
                  
          // 創(chuàng)建StandardClassLoader對象,并返回

                  String array[] 
          = (String[]) list.toArray(new String[list.size()]);
                  StandardClassLoader classLoader 
          = null;
                  
          if (parent == null){
                     classLoader 
          = new StandardClassLoader(array); 
                  }
          else{
                       classLoader 
          = new StandardClassLoader(array, parent);
                  }
                     
                  classLoader.setDelegate(
          true);
                  
          return (classLoader);

              }

              
          /**
               * 輸出日志
               
          */

              
          private static void log(String message) {
                  System.out.print(
          "ClassLoaderFactory:  ");
                  System.out.println(message);
              }

              
          /**
               * 輸出日志和異常信息
               
          */

              
          private static void log(String message, Throwable exception) {
                  log(message);
                  exception.printStackTrace(System.out);
              }


          }

          3.3 - org/apache/catalina/loader/StandardClassLoader.java
          類載入器

          3.4 - org/apache/catalina/startup/SecurityClassLoad.java
          該類僅包含一個靜態(tài)方法,用來為catalinaLoader載入一些類

           


          package org.apache.catalina.startup;


          /**
           * Static class used to preload java classes when using the
           * Java SecurityManager so that the defineClassInPackage
           * RuntimePermission does not trigger an AccessControlException.
           *
           * 
          @author Glenn L. Nielsen
           * 
          @version $Revision: 1.1 $ $Date: 2001/12/30 01:58:20 $
           
          */




          /**
           * 該類只有一個靜態(tài)方法,其作用僅僅相當(dāng)于一個函數(shù)
           * 該靜態(tài)方法負(fù)責(zé)載入一些指定的類
           * package org.apache.catalina.core
           * package org.apache.catalina.connector
           * package org.apache.catalina.loader
           * package org.apache.catalina.session
           * package org.apache.catalina.util
           * 這些包都在$CATALINA_HOME/server/catalina.jar文件中
           * (由此看來,該靜態(tài)方法的合法參數(shù)僅為catalinaLoader?)
           
          */



          public final class SecurityClassLoad {

              
          static void securityClassLoad(ClassLoader loader)
                  
          throws Exception {

                  
          if( System.getSecurityManager() == null )return;

                  String basePackage 
          = "org.apache.catalina.";
                  loader.loadClass(basePackage 
          + "core.ApplicationContext$PrivilegedGetRequestDispatcher");
                  loader.loadClass(basePackage 
          + "core.ApplicationContext$PrivilegedGetResource");
                  loader.loadClass(basePackage 
          + "core.ApplicationContext$PrivilegedGetResourcePaths");
                  loader.loadClass(basePackage 
          + "core.ApplicationContext$PrivilegedLogMessage");
                  loader.loadClass(basePackage 
          + "core.ApplicationContext$PrivilegedLogException");
                  loader.loadClass(basePackage 
          + "core.ApplicationContext$PrivilegedLogThrowable");
                  loader.loadClass(basePackage 
          + "core.ApplicationDispatcher$PrivilegedForward");
                  loader.loadClass(basePackage 
          + "core.ApplicationDispatcher$PrivilegedInclude");
                  loader.loadClass(basePackage 
          + "core.ContainerBase$PrivilegedAddChild");
                  loader.loadClass(basePackage 
          + "connector.HttpRequestBase$PrivilegedGetSession");
                  loader.loadClass(basePackage 
          + "connector.HttpResponseBase$PrivilegedFlushBuffer");
                  loader.loadClass(basePackage 
          + "loader.WebappClassLoader$PrivilegedFindResource");
                  loader.loadClass(basePackage 
          + "session.StandardSession");
                  loader.loadClass(basePackage 
          + "util.CookieTools");
                  loader.loadClass(basePackage 
          + "util.URL");
                  loader.loadClass(basePackage 
          + "util.Enumerator");
                  loader.loadClass(
          "javax.servlet.http.Cookie");

              }

          }


          posted on 2011-12-27 10:25 Eric_jiang 閱讀(623) 評論(1)  編輯  收藏 所屬分類: Java

          Feedback

          # re: ClassLoader介紹 2011-12-27 10:29 Eric_jiang
          http://www.jobeast.com/puyufanyi  回復(fù)  更多評論
            

          主站蜘蛛池模板: 孟州市| 阳山县| 平潭县| 宜宾市| 达日县| 焦作市| 曲阳县| 建阳市| 镇巴县| 泸定县| 阿拉尔市| 卢氏县| 平安县| 廊坊市| 双辽市| 六盘水市| 康乐县| 山东| 佛坪县| 蓝田县| 葵青区| 淳化县| 潮安县| 普兰店市| 临城县| 德昌县| 华阴市| 孝感市| 淳安县| 九龙城区| 平阴县| 石楼县| 西城区| 得荣县| 东港市| 米易县| 三原县| 临汾市| 邳州市| 镇平县| 泸定县|