一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Tomcat 源代碼分析之ClassLoader

 陳湖雨_毓 2012-02-16

Tomcat 源代碼分析之ClassLoader

此系列文章皆為Tomcat 7.0代碼代碼分析。

 

1. ClassLoader基礎(chǔ)知識(shí)

1.1. Parent-Child委托模型

 

我們知道Java系統(tǒng)中,類加載器的默認(rèn)加載方式是采用Parent-Child委托方式加載類的,即就是說(shuō),先嘗試使用父類加載器加載類,如果沒(méi)有找到,才自己加載該類,可以看到,這是一個(gè)遞歸的加載過(guò)程,核心代碼大致如下:

Java代碼  收藏代碼
  1. protected Class<?> loadClass(String name, boolean resolve)  
  2.         throws ClassNotFoundException  
  3.     {  
  4.         synchronized (getClassLoadingLock(name)) {  
  5.             // First, check if the class has already been loaded  
  6.             Class c = findLoadedClass(name);  
  7.             if (c == null) {  
  8.                 ……  
  9.                 try {  
  10.                     if (parent != null) {  
  11.                         c = parent.loadClass(name, false);  
  12.                     } else {  
  13.                         c = findBootstrapClassOrNull(name);  
  14.                     }  
  15.                 } catch (ClassNotFoundException e) {  
  16.                     // ClassNotFoundException thrown if class not found  
  17.                     // from the non-null parent class loader  
  18.                 }  
  19.   
  20.                 if (c == null) {  
  21.                     // If still not found, then invoke findClass in order  
  22.                     // to find the class.  
  23.                     …  
  24.                     c = findClass(name);  
  25.                     ……  
  26.                 }  
  27.             }  
  28.             ……  
  29.             return c;  
  30.         }  
  31.     }  
 很多ClassLoader的繼承類都默認(rèn)了這種加載方式,其中用途比較廣泛的有URLClassLoader。

1.2. 類加載器運(yùn)行時(shí)模型:

 

當(dāng)一個(gè)JVM啟動(dòng)時(shí),至少有三個(gè)ClassLoader會(huì)被啟動(dòng):

1. Bootstrap 類加載器

加載Java核心包,它們被置放在(<JAVA_HOME>/lib目錄下,這部分是JVM的一部分,往往使用native code完成

2. Extensions類加載器

加載Java擴(kuò)展包,即位于<JAVA_HOME>/lib/ext下的包,這里要注意的是,有些JVM的這個(gè)加載器和Bootstrap類加載器是同一個(gè)加載器,而Sun是把二者分開(kāi)的,其實(shí)現(xiàn)類為sun.misc.Launcher$ExtClassLoader。

3. System類加載器

這個(gè)類加載器加載CLASSPATH下的類,Sun的 默認(rèn)實(shí)現(xiàn)是sun.misc.Launcher$ExtClassLoader。

這三者之間的父子關(guān)系是:Bootstrap類加載器是Extensions類加載器的父類加載器,而Extensions類加載器是System類加載器的父類加載器。

2. Tomcat Classloader模型

Tomcat 7.0的ClassLoader加載層次模型如下圖所示:

 

 

這個(gè)模型和之前Tomcat 5.5之前有些不同,因?yàn)橹暗某^(guò)Common類加載器之外,還有Catalina類加載器和Shared類加載器,這個(gè)只能導(dǎo)致更多的配置和概念,已經(jīng)不再使用了,雖然還可以進(jìn)行配置。

1. Common類加載器:加載$CATALINA_HOME/lib和$CATALINA_BASE/lib下的class文件和jar包以及旗下的資源文件,這些文件將會(huì)被所有Web應(yīng)用共有,也會(huì)被Tomcat運(yùn)行時(shí)用到。其配置在catalina.properties下,如果沒(méi)有配置,則默認(rèn)使用System類加載器,配置示例:
common.loader=${catalina.home}/lib,${catalina.home}/lib/*.jar
2. App類加載器:Web 應(yīng)用的類加載器,Web應(yīng)用下的資源文件,class文件盒jar包,按照J(rèn)ava Web規(guī)范的標(biāo)準(zhǔn),它們位于Web應(yīng)用的/WEB-INF/classes和/WEB-INF/lib文件夾下。

3. 類加載器的實(shí)現(xiàn)

 

Tomcat類加載器其實(shí)有三個(gè)類實(shí)現(xiàn):StandardClassLoader,WebappClassLoader和JasperLoader,這三個(gè)類加載器都是URLClassLoader的子類。不同的是,StandardClassLoader并沒(méi)有客戶化URLClassLoader方法,即,它也是采用委托的方式加載類的。而其他都覆寫(xiě)了loadClass()方法。

1. StandardClassLoader類加載器會(huì)創(chuàng)建Common類加載器的實(shí)例。

2. WebappClassLoader為每個(gè)應(yīng)用創(chuàng)建類加載器實(shí)例,對(duì)于加載Web應(yīng)用的類時(shí),我們并非推薦使用父子委托模型,但是必須保證以java.*和javax.*開(kāi)頭的包必須由System類加載器加載,即最終由Bootstrap加載器加載。

核心代碼如下:

Java代碼  收藏代碼
  1. public Class loadClass(String name, boolean resolve)  
  2.         throws ClassNotFoundException {  
  3.   
  4.        ……  
  5.   
  6.         // (0) Check our previously loaded local class cache  
  7.         clazz = findLoadedClass0(name);  
  8.         if (clazz != null) {  
  9.             if (log.isDebugEnabled())  
  10.                 log.debug("  Returning class from cache");  
  11.             if (resolve)  
  12.                 resolveClass(clazz);  
  13.             return (clazz);  
  14.         }  
  15.   
  16.         // (0.1) Check our previously loaded class cache  
  17.         clazz = findLoadedClass(name);  
  18.         if (clazz != null) {  
  19.             if (log.isDebugEnabled())  
  20.                 log.debug("  Returning class from cache");  
  21.             if (resolve)  
  22.                 resolveClass(clazz);  
  23.             return (clazz);  
  24.         }  
  25.   
  26.         // (0.2) Try loading the class with the system class loader, to prevent  
  27.         //       the webapp from overriding J2SE classes  
  28.        //保證以java.*和javax.*開(kāi)頭的包必須由System類加載器加載  
  29.         try {  
  30.             clazz = system.loadClass(name);  
  31.             if (clazz != null) {  
  32.                 if (resolve)  
  33.                     resolveClass(clazz);  
  34.                 return (clazz);  
  35.             }  
  36.         } catch (ClassNotFoundException e) {  
  37.             // Ignore  
  38.         }  
  39.   
  40.         ……  
  41.   
  42.         boolean delegateLoad = delegate || filter(name);  
  43.   
  44.         // (1) Delegate to our parent if requested  
  45.         //Mbeans加載時(shí),是否采用delegate方式  
  46.         if (delegateLoad) {  
  47.             if (log.isDebugEnabled())  
  48.                 log.debug("  Delegating to parent classloader1 " + parent);  
  49.             ClassLoader loader = parent;  
  50.             if (loader == null)  
  51.                 loader = system;  
  52.             try {  
  53.                 clazz = loader.loadClass(name);  
  54.                 if (clazz != null) {  
  55.                     if (log.isDebugEnabled())  
  56.                         log.debug("  Loading class from parent");  
  57.                     if (resolve)  
  58.                         resolveClass(clazz);  
  59.                     return (clazz);  
  60.                 }  
  61.             } catch (ClassNotFoundException e) {  
  62.                 ;  
  63.             }  
  64.         }  
  65.   
  66.         // (2) Search local repositories  
  67.        //先本地加載,不委托父加載器加載  
  68.         if (log.isDebugEnabled())  
  69.             log.debug("  Searching local repositories");  
  70.         try {  
  71.             clazz = findClass(name);  
  72.             if (clazz != null) {  
  73.                 if (log.isDebugEnabled())  
  74.                     log.debug("  Loading class from local repository");  
  75.                 if (resolve)  
  76.                     resolveClass(clazz);  
  77.                 return (clazz);  
  78.             }  
  79.         } catch (ClassNotFoundException e) {  
  80.             ;  
  81.         }  
  82.   
  83.         // 最后使用父加載器加載  
  84.         if (!delegateLoad) {  
  85.             if (log.isDebugEnabled())  
  86.                 log.debug("  Delegating to parent classloader at end: " + parent);  
  87.             ClassLoader loader = parent;  
  88.             if (loader == null)  
  89.                 loader = system;  
  90.             try {  
  91.                 clazz = loader.loadClass(name);  
  92.                 if (clazz != null) {  
  93.                     if (log.isDebugEnabled())  
  94.                         log.debug("  Loading class from parent");  
  95.                     if (resolve)  
  96.                         resolveClass(clazz);  
  97.                     return (clazz);  
  98.                 }  
  99.             } catch (ClassNotFoundException e) {  
  100.                 ;  
  101.             }  
  102.         }  
  103.   
  104.         throw new ClassNotFoundException(name);  
  105.     }  

可以看到,并非簡(jiǎn)單的父子委托方式加載類

3. JasperLoader是為了加載jsp編譯成的servlet而創(chuàng)建的類加載器,它覆寫(xiě)了loadClass()方法,除過(guò)加載org.apache.jsp.*的文件外,其他的均使用父加載器加載。

核心代碼如下:

Java代碼  收藏代碼
  1. public Class loadClass(final String name, boolean resolve)  
  2.         throws ClassNotFoundException {  
  3.   
  4.         Class clazz = null;                  
  5.                                              
  6.         // (0) Check our previously loaded class cache  
  7.         clazz = findLoadedClass(name);       
  8.         if (clazz != null) {                 
  9.             if (resolve)                     
  10.                 resolveClass(clazz);         
  11.             return (clazz);          
  12.         }                            
  13.                             
  14.         // (.5) Permission to access this class when using a SecurityManager  
  15.         ……  
  16.   
  17.     if( !name.startsWith(Constants.JSP_PACKAGE_NAME) ) {  
  18.             // Class is not in org.apache.jsp, therefore, have our  
  19.             // parent load it  
  20.             clazz = parent.loadClass(name);              
  21.         if( resolve )  
  22.         resolveClass(clazz);  
  23.         return clazz;  
  24.     }  
  25.         //所有的以org.apache.jsp.*開(kāi)頭的文件都由該類加載器加載。  
  26.     return findClass(name);  
  27.     }  
 

 

今天就講到這里了。

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    日韩黄色一级片免费收看| 国产一区二区在线免费| 亚洲欧洲一区二区综合精品| 午夜国产成人福利视频| 91精品视频全国免费| 黑鬼糟蹋少妇资源在线观看| 欧美日韩精品久久亚洲区熟妇人| 最好看的人妻中文字幕| 国产内射一级二级三级| 亚洲人妻av中文字幕| 麻豆一区二区三区精品视频| 亚洲伊人久久精品国产| 久七久精品视频黄色的| 亚洲欧美日韩在线中文字幕| 中日韩美女黄色一级片| 少妇一区二区三区精品| 青青免费操手机在线视频| 国产亚洲欧美一区二区| 日本成人中文字幕一区| 久久精品国产99精品亚洲| 国产在线小视频你懂的| 丰满少妇被粗大猛烈进出视频| 久久国产亚洲精品赲碰热| 福利一区二区视频在线| 精品久久少妇激情视频| 精品久久久一区二区三| 国产精品日韩精品一区| 亚洲国产精品久久网午夜| 91亚洲精品国产一区| 激情少妇一区二区三区| 亚洲男人的天堂色偷偷| 国产真人无遮挡免费视频一区| 亚洲精品成人午夜久久| 国产传媒免费观看视频| 91亚洲国产成人久久| 欧美日韩中国性生活视频| 日本丰满大奶熟女一区二区| 日韩欧美国产精品中文字幕| 男人和女人黄 色大片| 日韩在线视频精品视频| 亚洲国产四季欧美一区|