在各類Tomcat相關書籍,書上都提到了其類加載器結構:java
在Tomcat 7或者8中,共享類和Catalina類加載器在catalina.properties中都是沒配置的,請看:web
因此,catalina和shared是直接把common的類加載器賦值給了它們,這三者其實都是同一個類加載器。apache
此次咱們來驗證下,方法是經過jmap導出內存堆棧,而後用eclipse 的MAT工具進行分析。bootstrap
個人tomcat是7.0.68,webapps只有默認的幾個應用。tomcat
在命令行執行下面語句,獲取pid:app
ps -ef|grep java
而後執行:eclipse
jmap -dump:live,format=b,file=heap.bin 此處爲pid佔位符
用MAT打開heap.bin後,會讓你選擇分析的類型,咱們選擇Component Report便可。webapp
接下來,正式開始分析:工具
咱們知道,tomcat中的應用加載器,類名即爲org.apache.catalina.loader.WebappClassLoader。spa
咱們這裏,直接用oql語言(eclipse mat中語法)來查詢該類的對象:
能夠看到,共有5個對象。
5個對象,分別對應了默認的5個應用,manager、host manaer、docs、root、example。
咱們選擇第一個,查看下圖,可知,該classload是爲manager應用服務的,其餘幾個就不一一截圖了:
從上圖也能夠簡單看出來,類加載路徑就是簡單地去本身context目錄下的 WEB-INF/lib 、WEB-INF/classes下查找。
(固然,具體的實現沒這麼簡單,會根據類名稱以及delegate 參數,選擇是給j2seClassLoader加載(加載jre/lib/ext下的),仍是給parent
來加載,仍是本身加載。)
按照理論上說,WebappClassLoader的parent,即爲common類加載器,主要加載tomcat本身的類,即catalina.base中lib下面的類。
咱們上圖看看:
從圖上能夠看出來,確實沒騙我,加載的類路徑確實就是tomcat的lib目錄。
咱們順便,驗證下,common、server、share都執行同一個引用。下圖能夠看出來,確實沒錯。
咱們繼續往上追溯,common的parent,應該是jdk的默認類加載器,類型爲sun.misc.Launcher$AppClassLoader,主要負責加載classpath下的東西。
這裏,看看咱們的classpath是哪一個:
上圖能夠看出來,classpath下,只有2個類(忽略greys-agent.jar,那個是調試工具),即bootstrap.jar 和tomcat-juli.jar(Tomcat內部日誌)。
到這裏,咱們的驗證基本就結束了。
這裏,從第四點,我有一些感想,彷佛明白了:
爲何tomcat的啓動源碼裏,即bootstrap類中,一上來就要設置線程上下文類加載器。
緣由就是,BootStrap是應用類加載器加載的,只加載了Bootstrap和tomcat-juli.jar。而tomcat/lib下無法加載。
因此就立刻新建了commonLoader,(和catalinLoader、sharedLoader同一個引用),並且設置爲線程類加載器,方便進行後續的類加載。
說實話,但我以爲,tomcat的bootstrp.jar和tomcat-juli.jar爲啥不直接放到lib目錄下,你們都直接使用common類加載器算了,搞不懂搞不懂。
今天分享就到這。
ps:題外話,爲啥上一篇寫的openjdk 源碼編譯、調試的文章,根本沒幾我的看呢。。。畢生絕學都拿出來了,哭。。