<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    海闊天空

    I'm on my way!
    隨筆 - 17, 文章 - 69, 評論 - 21, 引用 - 0
    數據加載中……

    啟動期間的加載類的順序和過程

    Tomcat啟動時classloader加載順序
    Tomcat的class加載的優先順序一覽  
    1.最先是$JAVA_HOME/jre/lib/ext/下的jar文件。  
    2.環境變量CLASSPATH中的jar和class文件。  
    3.$CATALINA_HOME/common/classes下的class文件。  
    4.$CATALINA_HOME/commons/endorsed下的jar文件。  
    5.$CATALINA_HOME/commons/i18n下的jar文件。  
    6.$CATALINA_HOME/common/lib   下的jar文件。  
    (JDBC驅動之類的jar文件可以放在這里,這樣就可以避免在server.xml配置好數據源卻出現找不到JDBC   Driver的情況。)  
    7.$CATALINA_HOME/server/classes下的class文件。  
    8.$CATALINA_HOME/server/lib/下的jar文件。  
    9.$CATALINA_BASE/shared/classes   下的class文件。  
    10.$CATALINA_BASE/shared/lib下的jar文件。  
    11.各自具體的webapp   /WEB-INF/classes下的class文件。  
    12.各自具體的webapp   /WEB-INF/lib下的jar文件。  
    class的搜尋順序如下:  
    -------------  
    Bootstrap   classes   of   your   JVM    
    System   class   loader   classses   (described   above)    
    /WEB-INF/classes   of   your   web   application    
    /WEB-INF/lib/*.jar   of   your   web   application    
    $CATALINA_HOME/common/classes    
    $CATALINA_HOME/common/endorsed/*.jar    
    $CATALINA_HOME/common/i18n/*.jar    
    $CATALINA_HOME/common/lib/*.jar    
    $CATALINA_BASE/shared/classes    
    $CATALINA_BASE/shared/lib/*.jar    
    --------------  
    因此放在不同webapp里的class文件,會被classloader加載成不同的實例。  
    例如假設下面兩個不同內容的class。分別放在不同的webapp的class目錄下。  
    package   com.lizongbo;  
    public   class   TestClass   {  
          private   String   NAME="lizongbo";  
    }  
    package   com.lizongbo;  
    public   class   TestClass   {  
          private   String   NAME="li_zongbo";  
    }  
    在不同的webapp得到的com.lizongbo.NAME結果是不同的,且互不影響。  
    但是注意,以下包名開頭的class例外:  
    javax.*    
    org.xml.sax.*    
    org.w3c.dom.*    
    org.apache.xerces.*    
    org.apache.xalan.*    
    ps,注意.在各個jar中的\META-INF\MAINFEST.MF文件里Class-Path鍵值對,也會提供jar的加載優先順序。  
    例如某jar的MAINFEST.MF內容如下:  
    Manifest-Version:   1.0  
    Created-By:   lizongbo  
    Class-Path:   commons-beanutils.jar  
    Class-Path:   commons-collections.jar  
    Class-Path:   commons-dbcp.jar  
    Class-Path:   commons-digester.jar  
    Class-Path:   commons-logging.jar  
    Class-Path:   commons-pool.jar  
    Class-Path:   commons-services.jar  
    Class-Path:   commons-validator.jar  
    Class-Path:   jakarta-oro.jar  
    Main-Class:   com.lizongbo.MyTestClass  
    那么在加載這個jar的時候,會先在此jar所在目錄下依次先加載commons-beanutils.jar,commons-collections.jar。。。等jar文件。  
    在不同的地方放置jar和class可能會產生意想不到的后果,,尤其是不同版本的jar文件,因此在實際應用部署web應用時候要特別留心.  
    例如   使用javamail常見的一個出錯信息:  
    javax.mail.NoSuchProviderException:   No   provider   for   smtp  
    其真實原因就很可能如下:  
    在不同的加載jar的目錄下放置了不同版本的mail.jar,比如一個是javamail1.3.1的mail.jar  
    在D:\jakarta-tomcat-5.5.8\common\lib下,而另外一個是javamail1.3.2的mail.jar在  
    D:\jakarta-tomcat-5.5.8\webapps\lizongbo\WEB-INF/lib下,  
    那么lizongbo這個webapp中使用到javamail進行郵件發送的時候,便會出現No   provider   for   smtp的錯誤。  
    *******************************************************************
    ClassLoader in Tomcat
    ************************************
    1 - Tomcat 的類載入器的結構


    Tomcat Server 在啟動的時候將構造一個ClassLoader樹,以保證模塊的類庫是私有的
    Tomcat Server的ClassLoader結構如下:


            +-----------------------------+

            |         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,用來在運行時動態地載入其它類
    系統默認的contextClassLoader是systemClassLoader,所以一般而言java程序在執行時可以使用JVM自帶的類、$JAVA_HOME/jre/lib/ext/中的類和$CLASSPATH/中的類
    可以使用 Thread.currentThread().setContextClassLoader(...); 更改當前線程的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 類的查找

    ClassLoader類中loadClass方法為缺省實現,用下面的順序查找類:

    1、調用findLoadedClass方法來檢查是否已經被加載。如果沒有則繼續下面的步驟。

    2、如果當前類裝載器有一個指定的委托父裝載器,則用委托父裝載器的loadClass方法加載類,也就是委托給父裝載器加載相應的類。

    3、如果這個類裝載器的委托層級體系沒有一個類裝載器加載該類,則使用類裝載器定位類的特定實現機制,調用findClass方法來查找類。



    4 - 部分原代碼分析


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

    Bootstrap中定義了三個classloader:commonLoader,catalinaLoader,sharedLoader.三者關系如下:


    // 注意三個自己定置的ClassLoader的層次關系:

                // systemClassLoader (root)

                  //   +--- commonLoader

                //          +--- catalinaLoader

                //          +--- sharedLoader


    Tomcat Server 線程的起點
    構造ClassLoader樹,通過Thread.currentThread().setContextClassLoader(catalinaLoader)設置當前的classloader為catalinaLoader。
    載入若干類,然后轉入org.apache.catalina.startup.Catalina類中



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

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

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

    (1) If a system class, use system class loader通過系統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 默認使用代理裝載器



    [ 查看代碼]


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


    根據設置創建并返回StandardClassLoader的實例


    [ 查看代碼]


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


    類載入器


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


    該類僅包含一個靜態方法,用來為catalinaLoader載入一些類


    [ 查看代碼]


    Appendix - 參考


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


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

    posted on 2009-07-01 18:44 石頭@ 閱讀(1007) 評論(0)  編輯  收藏 所屬分類: tomcat_core


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 国产免费人成视频尤勿视频| 成人精品视频99在线观看免费| 精品久久久久久亚洲中文字幕| 黄页网站免费观看| 亚洲真人日本在线| 日韩亚洲不卡在线视频中文字幕在线观看 | 日产亚洲一区二区三区| 久久久久久久久久国产精品免费| 亚洲人成网亚洲欧洲无码久久| 国产一级在线免费观看| 国产亚洲午夜高清国产拍精品 | 亚洲av无码一区二区三区在线播放| 免费无码又黄又爽又刺激| 日韩精品亚洲aⅴ在线影院| 亚洲精品456人成在线| 在线天堂免费观看.WWW| 国产偷v国产偷v亚洲高清| 亚洲av无码一区二区三区人妖 | 2019中文字幕免费电影在线播放 | 亚洲国产精品人久久电影| 国色精品卡一卡2卡3卡4卡免费| 亚洲不卡中文字幕| 日韩视频免费一区二区三区| 爱情岛亚洲论坛在线观看| 亚洲色婷婷综合开心网| 久久精品视频免费播放| 亚洲av日韩av综合| 免费午夜爽爽爽WWW视频十八禁| 国产精品亚洲片在线va| 国产国产人免费人成免费视频| 亚洲H在线播放在线观看H| 成人免费视频国产| 国产性生大片免费观看性| 亚洲男人天堂影院| 在线观看亚洲免费| 另类免费视频一区二区在线观看| 亚洲狠狠狠一区二区三区| 国产国产成年年人免费看片| 国内精品99亚洲免费高清| 亚洲精品自拍视频| 亚洲第一页综合图片自拍|