一、類加載器類型java
當啓動一個JVM時,bootstrap 類加載器就會加載java的核心類,例如:rt.jar中的類。bootstrap 類加載器是其餘類加載器的parent,它使惟一一個沒有parent的類加載器。接下來是extension 類加載器,它以bootstrap 類加載器做爲parent,它用來從Java系統變量java.ext.dir中的jar包中加載類的。第三個,也是最重要的一個就是開發者使用的system classpath 類加載器 。它是extension 類加載器 的child,它用來從Java系統變量java.class.path下面加載類,能夠經過 -classpath 來指定這個位置。編程
二、delegate委派模型bootstrap
注意類加載器的體系並非「繼承」體系,而是一個「委派」體系。大多數類加載器首先會到本身的parent中查找類或者資源,若是找不到,纔會在本身的本地進行查找。事實上,類加載器被定義加載哪些在parent中沒法加載到的類,這樣在較高層級的類加載器上的類型可以被「賦值」爲較低類加載器加載的類型。類加載器的委託行爲動機是爲了不相同的類被加載屢次。tomcat
三、服務端的反委派模型服務器
可是服務器端要求類加載器可以反轉委派原則,也就是先加載本地的類,若是加載不到,再到parent中加載。數據結構
JavaEE的 委派模型併發
每一個方塊都是一個類加載器,JavaEE規範推薦每一個模塊的類加載器先加載本類加載的內容,若是加載不到纔回到parent類加載器中嘗試加載。反轉委派原則的緣由是應用服務器中所攜帶的類庫並非應用所期待的,也許不適合應用開發者,一個常見的例子就是log4j的依賴在容器和不一樣的應用中都存在,可是它們的版本大都不一樣。app
四、tomcat開啓delegate模型spa
Tomcat的 類加載順序(開啓了delegate模式)繼承
在Tomcat中,默認的行爲是先嚐試在Bootstrap和Extension中進行類型加載,若是加載不到則在WebappClassLoader中進行加載,若是仍是找不到則在Common中進行查找。在Alibaba使用的Tomcat開啓了delegate模式,所以加載類型時會以parent類加載器優先。
五、類類型定義
在JVM中,如何肯定一個類型實例?答:全類名嗎?不是,是類加載器加上全類名。在JVM中,類型被定義在一個叫SystemDictionary 的數據結構中,該數據結構接受類加載器和全類名做爲參數,返回類型實例。
六、問題排查
類找不到 | 加載了不正確的類 | 多於一個類被加載 |
ClassNotFoundException NoClassDefFoundError | IncompatibleClassChangeError NoSuchMethodError NoSuchFieldError IllegalAccessError | ClassCastException LinkageError |
IDE class lookup (Ctrl+Shift+T in Eclipse)find . -name 「*.jar」 -exec jar -tf {} \; | grep DateUtils
使用middleware-detector |
經過在啓動參數中加 -verbose:class,觀察加載的類來自哪一個jar包 使用middelware-detector |
經過-verbose:class觀察 |
轉載自併發編程網 – ifeve.com本文連接地址: 深刻淺出ClassLoader