1. 程式人生 > >NoClassDefFoundError和ClassNotFoundException的不同

NoClassDefFoundError和ClassNotFoundException的不同

如果JVM或者ClassLoader在載入類時找不到對應的類,就會引發NoClassDefFoundErrorClassNotFoundException,這兩種錯誤都非常嚴重。由於不同的ClassLoader會從不同的地方載入類,有時是錯誤的CLASSPATH引發這類錯誤,有時是某個庫的jar包缺失引發這類錯誤。NoClassDefFoundErrorClassNotFoundException之間存在一些細微的不同點。

NoClassDefFoundError表示該類在編譯階段還可以找到,但是在執行Java應用的時候找不到了,有時靜態塊的初始化過程會導致NoClassDefFoundError

另外一方面,ClassNotFoundException和編譯期沒什麼關係,當你在程式執行時利用反射載入類時,就可能遇到ClassNotFoundException異常,例如載入SQL驅動時,對應的類載入器找不到驅動類。除了這些基本的不同,我們可以看看別的不同,以加深對NoClassDefFoundErrorClassNotFoundException的理解。

NoClassDefFoundError vs ClassNotFoundException

簡單來說,NoClassDefFoundErrorClassNotFoundException都是由於在CLASSPATH下找不到對應的類而引起的,通常是缺少對應的jar包,不過,JVM認為:(1)當應用執行時沒有找到對應的引用,則會丟擲java.lang.NoClassDefFoundError

;(2)當你在程式碼中顯式載入類(使用Class.forName())時沒有找到對應的類,則會丟擲java.lang.ClassNotFoundException。開發者經常遇到的情況是:ClassNotFoundException異常引起了ClassNoDefFoundError。

  1. NoClassDefFoundError是Error,是unchecked,因此也不需要使用try-catch或者finally語句塊包圍;另外,ClassNotFoundException是受檢異常(checked Exception),因此需要使用try-catch語句塊或者try-finally語句塊包圍,否則會導致編譯錯誤。

  2. 如果你在J2EE開發中遇到NoClassDefFoundError,那麼最有可能的原因就是存在多個類載入器和多個目標類,即我們常說的Jar包衝突——關於Jar包衝突,一般可以使用下面兩種方法解決:

  • 使用Maven Helper 這個外掛,可以排除掉大部分jar包衝突;
  • 根據命令mvn dependency:tree -Dverbose -Dincludes=:logback-classic
  1. 呼叫Class.forName()ClassLoader.findSystemClass()ClassLoader.loadClass()等方法時可能會引起java.lang.ClassNotFoundException

  2. NoClassDefFoundError是連結錯誤,發生在連結階段,當解析引用的時候找不到對應的類,就會丟擲java.lang.NoClassDefFoundErrorClassNotFoundException是異常,發生在執行階段。

首先我們來看一下文件中是如何定義的。

NoClassDefFoundError

Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.

The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.

如果jvm或者一個ClassLoader的例項嘗試去載入一個class的定義內容(普通方法的呼叫或者用new去建立這個class的例項)但是沒有找到這個class的資訊。

ClassNotFoundException

Thrown when an application tries to load in a class through its string name using:
The forName method in class Class.
The findSystemClass method in class ClassLoader .
The loadClass method in class ClassLoader.
but no definition for the class with the specified name could be found.

As of release 1.4, this exception has been retrofitted to conform to the general purpose exception-chaining mechanism. The "optional exception that was raised while loading the class" that may be provided at construction time and accessed via the getException() method is now known as the cause, and may be accessed via the Throwable.getCause() method, as well as the aforementioned "legacy method."

當一個應用嘗試通過Class.forName("class的名字")去載入這個class的時候,但是卻沒有找到。

我們只需要去關注比較重要的資訊即可。需要注意到的是,NoClassDefFoundError是一個error並非一個異常,而是由LinkageError派生出的,但是ClassNotFoundException則是由ReflectiveOperationException派生的。

通過上面的jdk的文件說明可以很清楚的看出來:

NoClassDefFoundError出現的時機是當你真正使用這個類的資訊的時候,當class-path上沒有這個類的時候會出現。

ClassNotFoundException出現的時機就是一些反射操作,通過名稱在Runtime去動態載入這個類的資訊。


作者:杜琪
連結:https://www.jianshu.com/p/93d0db07d2e3
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。