由於須要用到了外部jar中的Class,卻在使用時遇到了NoClassDefFoundError,不過最終解決了,留下一個筆記供之後參考。 首先分析一下ClassNoDefFoundError異常,平時熟知的是ClassNotFoundException。ClassNotFoundException是找不到類的異常,那NoClassDefFoundError呢?其實也是找不到類,不過二者有着原理性的區別。java
爲類在加載時發現的異常,通常是由於要使用的類在ClassLoader中(由ClassLoder.getSystemClassLoader()得到)找不到,通常是依賴未在classpath中形成。工具
此錯誤繼承自 java.lang.LinkageError,是java.lang.Error類的派生類。含義是使用Class時JVM沒法正確得到Class的實例數據(定義的方法、父類、接口、字段等成員)。二者區別在於前者在加載類時找不到類,是屬於編譯時就可能發現的異常。後者是類加載成功後但沒法使用。spa
筆者遇到的問題呢就與這兩個異常有關。先說明一下是如何使用的吧。 首先因爲須要在動態使用一堆jar包中的Class,因而使用URLClassLoader把對應的Jar包所有包含。而後使用這個classLoader動態加載類來使用(使用Reflections查找被某些註解過的類)。 因爲Class就存在於diy的ClassLoader的範圍,Class加載成功,getCanonicalName()得到類全路徑正常。而後繼續去讀取Class中定義的字段、方法中被部分註解過的進行篩選。就在getDeclaredFields()或getDeclaredMethods()方法被調用時卻拋出NoClassDefFoundError。而異常中的類倒是這個Class內被引用過的類(暫叫DependencyClass),但DependencyClass在diy的ClassLoader的範圍,單獨加載也能成功加載。.net
繼承查看異常信息,原來是NoClassDefFoundError中又包裹了一層ClassNotFoundException。 觀其異常調用堆棧是在使用當前調用類的ClassLoader(sun.reflect.Reflection.getCallerClass()加載的ClassLoader)來加載Class的依賴。但當前調用類的ClassLoader並不存在DependencyClass。blog
找到緣由問題就快解決了,由於是調用類所在ClassLoader找不到依賴的Class,那能夠進行幾種方式解決:繼承
以上內容純屬我的經驗,不對之處歡迎來懟。接口