NoCassDefFoundError緣由分析

由於須要用到了外部jar中的Class,卻在使用時遇到了NoClassDefFoundError,不過最終解決了,留下一個筆記供之後參考。 首先分析一下ClassNoDefFoundError異常,平時熟知的是ClassNotFoundException。ClassNotFoundException是找不到類的異常,那NoClassDefFoundError呢?其實也是找不到類,不過二者有着原理性的區別。java

ClassNotFoundException

爲類在加載時發現的異常,通常是由於要使用的類在ClassLoader中(由ClassLoder.getSystemClassLoader()得到)找不到,通常是依賴未在classpath中形成。工具

NoClassDefFoundError

此錯誤繼承自 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,那能夠進行幾種方式解決:繼承

  1. 在工程的依賴中添加找不到類的依賴,這樣作會增長依賴。
  2. 在調用類以前得到系統ClassLoader,將找不到類的jar添加到ClassLoader的依賴中(AppClassLader繼承於URLClassLoader可經過反射修改ClassLoader來添加Jar)這種方法的依賴jar只能添加不能刪減,可能影響系統穩定性) 具體方法見 https://blog.csdn.net/fd2025/article/details/80538468
  3. 將方法代碼寫成工具,與diy的ClassLoader中的jar一塊兒加載,經過反射+反射方式實現。

以上內容純屬我的經驗,不對之處歡迎來懟。接口

相關文章
相關標籤/搜索