[Tomcat] Tomcat的classloader

定義

同其餘服務器應用同樣,tomcat安裝了各類classloader(classes that implement java.lang.ClassLoader)html

                       Bootstrap
                          |
                       System
                          |
                       Common
                      /      \
                 Catalina   Shared
                           /     \
                       Webapp1  Webapp2 ...
                         /          /
                      Jasper1   Jasper2
  • Bootstrap: contains the basic runtime classes provided by the Java Virtual Machine, plus any classes from JAR files present in the System Extensions directory ($JAVA_HOME/jre/lib/ext). Note: some JVMs may implement this as more than one class loader, or it may not be visible (as a class loader) at all. 
  • System: 加載系統環境變量 CLASSPATH 指定的Jars. 全部加載的類對Tomcat內部classes和web applications可見。可是tomcat腳本($CATALINA_HOME/bin/catalina.sh 或 %CATALINA_HOME%\bin\catalina.bat)會徹底忽略掉CLASSPATH,只加載%CATALINA_HOME%/bin目錄下的bootstrap.jar、tomcat-juli.jar、commons-daemon.jar。除非經過$CATALINA_HOME/bin/setenv.sh指定。
  • Common: 加載額外的Jars,全部加載的類對Tomcat內部classes和web applications可見。
  • WebAppX: A class loader is created for each web application that is deployed in a single Tomcat instance. All unpacked classes and resources in the /WEB-INF/classes directory of your web application, plus classes and resources in JAR files under the /WEB-INF/lib directory of your web application, are made visible to this web application, but not to other ones.

Therefore, from the perspective of a web application, class or resource loading looks in the following repositories, in this order:java

  • Bootstrap classes of your JVM
  • /WEB-INF/classes of your web application
  • /WEB-INF/lib/*.jar of your web application
  • System class loader classes (described above)
  • Common class loader classes (described above)

If the web application class loader is configured with <Loader delegate="true"/> then the order becomes:web

  • Bootstrap classes of your JVM
  • System class loader classes (described above)
  • Common class loader classes (described above)
  • /WEB-INF/classes of your web application
  • /WEB-INF/lib/*.jar of your web application

配置

JVM Classloader

首先,你須要瞭解一下JVM的Classloader機制(詳細請自行google之)。
簡而言之,JVM的classloader加載繼承關係分爲BootstarpClassLoader --> ExtClassLoader --> SystemClassLoader,應用的WebAppClassLoader繼承自SystemClassLoader,在加載具體某個類時,通常會先委託給父類ClassLoader,當父類ClassLoader沒法加載成功時,纔會再由子類ClassLoader嘗試加載,這就是所謂的delegate機制。apache

catalina.properties

其次,Tomcat在jvm的ClassLoader機制上增長了幾個繼承層次。
SystemClassLoader --> CommonClassLoader -->(ServerClassLoader | SharedClassLoader --> WebAppClassLoader)。
CommonClassLoader用來加載${CATALINA_HOME}/conf/catalina.properties中common.loader配置目錄下的類文件,通常是用來加載${CATALINA_HOME}/lib下的文件。該loader加載的類爲tomcat服務器和tomcat下面的全部webApp所共享。
ServerClassLoader用來加載${CATALINA_HOME}/conf/catalina.properties中server.loader配置目錄下的類文件,通常是用來加載${CATALINA_HOME}/server下的文件。該loader加載的類爲tomcat服務器所獨有核心類,tomcat下面的WebApp沒法訪問。
SharedClassLoader用來加載${CATALINA_HOME}/conf/catalina.properties中shared.loader配置目錄下的類文件,通常是用來加載${CATALINA_HOME}/shared下的文件。該loader加載的類爲tomcat下面的全部webApp所共享。
WebAppClassLoader用來加載${CATALINA_HOME}/webapps/目錄下每一個WebApp應用的/WEB-INF/class,/WEB-INF/lib的類文件,每一個WebApp對應一個WebAppClassLoader,用來加載其所須要的類文件。bootstrap

Delegate

最後,說一下delegate配置的意義。
True,表示tomcat將遵循JVM的delegate機制,即一個WebAppClassLoader在加載類文件時,會先遞交給SharedClassLoader加載,SharedClassLoader沒法加載成功,會繼續向本身的父類委託,一直到BootstarpClassLoader,若是都沒有加載成功,則最後由WebAppClassLoader本身進行加載。
False,表示將不遵循這個delegate機制,即WebAppClassLoader在加載類文件時,會優先本身嘗試加載,若是加載失敗,纔會沿着繼承鏈,依次委託父類加載。segmentfault

在此說一下配置爲False須要注意的問題:一旦配置爲False,若是你在WebApp中本身定義了一個java.lang.String,則這個String類會有可能覆蓋掉jdk中的String類,這也許不是你想要的結果。另外對於多個WebApp公用jar包,你可能會放到${CATALINA_HOME}/shared目錄中共享,可是一不當心在應用的/WEB-INF/lib中也包含了一個同名的但版本不一致的jar的話,這就有可能會致使不少奇怪的問題。tomcat

Reference

  • https://segmentfault.com/q/1010000000155690
  • http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html