隨筆-109  評論-187  文章-25  trackbacks-0

          ClassLoader in Tomcat (http://rosonsandy.blogdriver.com/rosonsandy/871539.html


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

          Tomcat Server 在啟動(dòng)的時(shí)候?qū)?gòu)造一個(gè)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 的工作原理

          每個(gè)運(yùn)行中的線程都有一個(gè)成員contextClassLoader,用來在運(yùn)行時(shí)動(dòng)態(tài)地載入其它類
          系統(tǒng)默認(rèn)的contextClassLoadersystemClassLoader,所以一般而言java程序在執(zhí)行時(shí)可以使用JVM自帶的類、$JAVA_HOME/jre/lib/ext/中的類和$CLASSPATH/中的類
          可以使用
          Thread.currentThread().setContextClassLoader(...); 更改當(dāng)前線程的contextClassLoader,來改變其載入類的行為

          ClassLoader 被組織成樹形,一般的工作原理是:
          1)
          線程需要用到某個(gè)類,于是contextClassLoader被請求來載入該類
          2) contextClassLoader
          請求它的父ClassLoader來完成該載入請求
          3)
          如果父ClassLoader無法載入類,則contextClassLoader試圖自己來載入

          注意 WebApp?ClassLoader的工作原理和上述有少許不同:
          它先試圖自己載入類(在ContextBase?/WEB-INF/...中載入類),如果無法載入,再請求父ClassLoader完成

          由此可得:
          -
          對于WEB APP線程,它的contextClassLoaderWebApp?ClassLoader
          -
          對于Tomcat Server線程,它的contextClassLoaderCatalinaClassLoader

          3 類的查找

          ClassLoader類中l(wèi)oadClass方法為缺省實(shí)現(xiàn),用下面的順序查找類:

          1、調(diào)用findLoadedClass方法來檢查是否已經(jīng)被加載。如果沒有則繼續(xù)下面的步驟。

          2、如果當(dāng)前類裝載器有一個(gè)指定的委托父裝載器,則用委托父裝載器的loadClass方法加載類,也就是委托給父裝載器加載相應(yīng)的類。

          3、如果這個(gè)類裝載器的委托層級體系沒有一個(gè)類裝載器加載該類,則使用類裝載器定位類的特定實(shí)現(xiàn)機(jī)制,調(diào)用findClass方法來查找類。

          4?- 部分原代碼分析

          4.1 - org/apache/catalina/startup/Bootstrap.java

          Bootstrap中定義了三個(gè)classloader:commonLoader,catalinaLoader,sharedLoader.三者關(guān)系如下:

          // 注意三個(gè)自己定置的ClassLoader的層次關(guān)系:?

          ??????????? // systemClassLoader (root)?

          ?? ?????????? //?? +--- commonLoader?

          ??????????? //????????? +--- catalinaLoader?

          ??????????? //????????? +--- sharedLoader

          Tomcat Server 線程的起點(diǎn)
          構(gòu)造ClassLoader樹,通過Thread.currentThread().setContextClassLoader(catalinaLoader)設(shè)置當(dāng)前的classloader為catalinaLoader。
          載入若干類,然后轉(zhuǎn)入org.apache.catalina.startup.Catalina類中

          4.2 org.apache.catalina.loader.StandardClassLoader.java

          通過看loadClass這個(gè)方法來看tomcat是如何加載類的,順序如下:

          (0) Check our previously loaded class cache查找已經(jīng)裝載的class
          ??????? clazz = findLoadedClass(name);

          (1)?If a system class, use system class loader通過系統(tǒng)classloader來裝載class

          ??????? ClassLoader loader = system;
          ??????????? clazz = loader.loadClass(name);

          (2) Delegate to our parent if requested如果有代理則使用父類classloader

          ??????????? ClassLoader loader = parent;
          ??????????? if (loader == null)
          ??????????????? loader = system;
          ????????????clazz = loader.loadClass(name);

          (3) Search local repositories 查找本地類池,比如$CATALINA_HOME/server

          ?????????? clazz = findClass(name);

          (4) Delegate to parent unconditionally 默認(rèn)使用代理裝載器

          [ 查看代碼]

          4.3 - org/apache/catalina/startup/ClassLoaderFactory.java

          根據(jù)設(shè)置創(chuàng)建并返回StandardClassLoader的實(shí)例

          [ 查看代碼]

          4.4 - org/apache/catalina/loader/StandardClassLoader.java

          類載入器

          4.5 - org/apache/catalina/startup/SecurityClassLoad.java

          該類僅包含一個(gè)靜態(tài)方法,用來為catalinaLoader載入一些類

          [ 查看代碼]

          Appendix - 參考

          [1] http://jakarta.apache.org/tomcat/ 中的Tomcat 4.1.x文檔Class Loader HOW-TO

          在一個(gè) JVM 中可能存在多個(gè) ClassLoader ,每個(gè) ClassLoader 擁有自己的 NameSpace 。一個(gè) ClassLoader 只能擁有一個(gè) class 對象類型的實(shí)例,但是不同的 ClassLoader 可能擁有相同的 class 對象實(shí)例,這時(shí)可能產(chǎn)生致命的問題。如 ClassLoaderA ,裝載了類 A 的類型實(shí)例 A1 ,而 ClassLoaderB ,也裝載了類 A 的對象實(shí)例 A2 。邏輯上講 A1=A2 ,但是由于 A1 A2 來自于不同的 ClassLoader ,它們實(shí)際上是完全不同的,如果 A 中定義了一個(gè)靜態(tài)變量 c ,則 c 在不同的 ClassLoader 中的值是不同的。

          posted on 2006-04-18 08:48 小小程序程序員混口飯吃 閱讀(454) 評論(0)  編輯  收藏 所屬分類: java
          主站蜘蛛池模板: 松滋市| 祁东县| 唐河县| 扎赉特旗| 淳安县| 桂平市| 汽车| 武夷山市| 清远市| 红原县| 吉木乃县| 始兴县| 罗甸县| 衡东县| 都匀市| 潍坊市| 江都市| 雅安市| 理塘县| 喀喇沁旗| 邢台县| 渭源县| 湘潭县| 锡林浩特市| 乐亭县| 钟山县| 砀山县| 军事| 车险| 海林市| 高安市| 聊城市| 大兴区| 江阴市| 长岛县| 进贤县| 五莲县| 林州市| 即墨市| 怀远县| 镇江市|