1. 程式人生 > >圖解Tomcat類載入機制

圖解Tomcat類載入機制

       之前學習javaMelody的原始碼,但是它是一個Maven的專案,與我們自己的web專案整合後無法直接斷點除錯。後來同事指導,說是直接把java類複製到src下就可以了。很納悶....為什麼會優先載入src下的java檔案(編譯出的class),而不是jar包中的class呢?

    現在瞭解tomcat的類載入機制,原來一切是這麼的簡單。

類載入

    在JVM中並不是一次性把所有的檔案都載入到,而是一步一步的,按照需要來載入。

    比如JVM啟動時,會通過不同的類載入器載入不同的類。當用戶在自己的程式碼中,需要某些額外的類時,再通過載入機制載入到JVM中,並且存放一段時間,便於頻繁使用。

    因此使用哪種類載入器、在什麼位置載入類都是JVM中重要的知識。

JVM類載入

    JVM類載入採用 父類委託機制,如下圖所示:

JVM中包括集中類載入器:

  1. BootStrapClassLoader 引導類載入器

  2. ExtClassLoader 擴充套件類載入器

  3. AppClassLoader 應用類載入器

  4. CustomClassLoader 使用者自定義類載入器

他們的區別上面也都有說明。需要注意的是,不同的類載入器載入的類是不同的,因此如果使用者載入器1載入的某個類,其他使用者並不能夠使用。

當JVM執行過程中,使用者需要載入某些類時,會按照下面的步驟(父類委託機制)

  1. 使用者自己的類載入器,把載入請求傳給父載入器,父載入器再傳給其父載入器,一直到載入器樹的頂層。

  2. 最頂層的類載入器首先針對其特定的位置載入,如果載入不到就轉交給子類。

  3. 如果一直到底層的類載入都沒有載入到,那麼就會丟擲異常ClassNotFoundException。

因此,按照這個過程可以想到,如果同樣在CLASSPATH指定的目錄中和自己工作目錄中存放相同的class,會優先載入CLASSPATH目錄中的檔案。

Tomcat類載入

    在tomcat中類的載入稍有不同,如下圖:

當tomcat啟動時,會建立幾種類載入器:

1、Bootstrap 引導類載入器

 

    載入JVM啟動所需的類,以及標準擴充套件類(位於jre/lib/ext下)

2、System 系統類載入器 

    載入tomcat啟動的類,比如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定。位於CATALINA_HOME/bin下。

3、Common 通用類載入器 

    載入tomcat使用以及應用通用的一些類,位於CATALINA_HOME/lib下,比如servlet-api.jar

4、webapp 應用類載入器

    每個應用在部署後,都會建立一個唯一的類載入器。該類載入器會載入位於 WEB-INF/lib下的jar檔案中的class 和 WEB-INF/classes下的class檔案。

當應用需要到某個類時,則會按照下面的順序進行類載入

1、使用bootstrap引導類載入器載入

2、使用system系統類載入器載入

3、使用應用類載入器在WEB-INF/classes中載入

4、使用應用類載入器在WEB-INF/lib中載入

5、使用common類載入器在CATALINA_HOME/lib中載入

問題擴充套件

  通過對上面tomcat類載入機制的理解,就不難明白 為什麼java檔案放在Eclipse中的src資料夾下會優先jar包中的class?

  這是因為Eclipse中的src資料夾中的檔案java以及webContent中的JSP都會在tomcat啟動時,被編譯成class檔案放在 WEB-INF/class中。

  而Eclipse外部引用的jar包,則相當於放在 WEB-INF/lib 中。

  因此肯定是 java檔案或者JSP檔案編譯出的class優先載入

  通過這樣,我們就可以簡單的把java檔案放置在src資料夾中,通過對該java檔案的修改以及除錯,便於學習擁有原始碼java檔案、卻沒有打包成xxx-source的jar包。

另外呢,開發者也會因為粗心而犯下面的錯誤。

  在 CATALINA_HOME/lib 以及 WEB-INF/lib 中放置了 不同版本的jar包,此時就會導致某些情況下報載入不到類的錯誤。

  還有如果多個應用使用同一jar包檔案,當放置了多份,就可能導致 多個應用間 出現類載入不到的錯誤。

參考

【1】Tomcat Class Loader:

http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html

【2】Tomcat 類載入機制:

http://blog.csdn.net/dc_726/article/details/11873343