系統的啓動流程:
tomcat通常從腳本啓動,查看腳本可知,startup.sh中調用了catalina.sh進行啓動,而在catalina.sh中,可以看到時啓動了Bootstrap類
org.apache.catalina.startup.Bootstrap "$@" start
從bootstrap類的main方法開始啓動,此類中有
private Object catalinaDaemon = null ;
protected ClassLoader commonLoader = null ;
protected ClassLoader catalinaLoader = null ;
等,首先new boostrap對象,調用init方法,init方法中先調用initClassLoader方法,獲取 三種ClassLoader,分別是:commonLoader、catalinaLoader 、sharedLoader ,在此說明一句,如果commonLoader初始化失敗,即沒有config配置文件,則將bootstrap的Classloader賦值給commonLoader。
先從commonLoader說起,
String value = . getProperty(name + ".loader");
此處使用了CatalinaProperties類,這個類有
static{
loadProperties();
}
會隨着類的加載而運行,加載了加載Catalina.Properties配置文件,通過字符串common.loader獲取此屬性文件對應的配置:
common.loader="${catalina.base}/lib", "${catalina.home}/lib/*.jar"
然後通過replace方法處理拿到的字符串,替換爲對應config目錄; D:\SVN\CodeLearning\Tomcat8\output\build/lib,根據四種模式:DIR JAR URL GLOB去掃描相應類,最後通過
ClassLoaderFactory. createClassLoader(repositories, parent)
方法,將String類型的加載路徑字符串穿進去,在此方法中使用LinkedHashSet,掃描將要加載的類,對應四種不同的模式,然後將這個LinkedHashSet.toArray,賦值給鏈表,最後
return new URLClassLoader(array);
把要加載路徑賦值進去,返回一個URLClassLoader,並加載各種類。所以commonLoader就是URLClassLoader。接上面的,如果沒有config,則使用bootstrap的ClassLoader給commonLoader。
同理,catalinaLoader和sharedLoader的加載方式:
catalinaLoader = createClassLoader( "server", commonLoader );
sharedLoader = createClassLoader("shared" , commonLoader );
由此可見commonloader是其父類加載器。不過server.loader和sharedLoader在Catalina.properties中沒配置屬性。當調用 catalinaLoader = createClassLoader( “server” , commonLoader );
sharedLoader = createClassLoader(“shared” , commonLoader );
時,
String value = CatalinaProperties. getProperty(name + ".loader");
if ((value == null) || (value.equals("")))
return parent;
由於properties文件沒有對應的server.loader和shared.loader屬性,古直接返回URLClassLoader加載器。
綜上,三種加載器初始化完畢,調用Thread. currentThread().setContextClassLoader( catalinaLoader);
將catalinaLoader設置爲當前線程的加載器。 然後調用
Class<?> startupClass = catalinaLoader.loadClass ("org.apache.catalina.startup.Catalina");
在加載catalina類,使用反射,調用其setParentClassLoader方法,參數爲java.lang.ClassLoader.
然後調用catalina的isAwait和start方法,啓動服務器。
Method method = catalinaDaemon.getClass().getMethod ("start" , (Class [] )null );