本文適用于當前面臨java.lang.ClassNotFoundException挑戰的Java初學者。 它將為您提供此常見Java異常的概述,這是一個示例Java程序,可支持您的學習過程和解決策略。
如果您對與更高級的類加載器相關的問題感興趣,我建議您復習有關java.lang.NoClassDefFoundError的文章系列,因為這些Java異常密切相關。
java.lang.ClassNotFoundException:概述
根據Oracle文檔,在類加載調用失敗后,將使用其字符串名稱引發ClassNotFoundException ,如下所示:
- Class.forName方法
- ClassLoader.findSystemClass方法
- ClassLoader.loadClass方法
換句話說,這意味著一個特定的Java類找不到或無法從您的應用程序當前上下文類加載器“運行”加載。
對于Java初學者來說,這個問題可能特別令人困惑。 這就是為什么我始終建議Java開發人員學習和完善他們在Java類加載器方面的知識的原因。 除非您參與動態類加載和使用Java Reflection API,否則您遇到的ClassNotFoundException錯誤不是來自應用程序代碼,而是來自引用API。 另一個常見的問題模式是錯誤包裝您的應用程序代碼。 我們將在本文結尾處回到解決策略。
java.lang。 ClassNotFoundException :示例Java程序
現在在下面找到一個非常簡單的Java程序,該程序通過Class.forName()和ClassLoader.loadClass()模擬兩種最常見的ClassNotFoundException方案。 請簡單地復制/粘貼并使用您選擇的IDE運行該程序( 此示例使用Eclipse IDE )。
Java程序允許您根據以下情況在問題場景1或問題場景2之間進行選擇。 根據您要研究的場景,只需更改為1或2。
#Class.forName()
private static final int PROBLEM_SCENARIO = 1;
#ClassLoader.loadClass()
private static final int PROBLEM_SCENARIO = 2;
#ClassNotFoundExceptionSimulator
package org.ph.javaee.training5;/*** ClassNotFoundExceptionSimulator* @author Pierre-Hugues Charbonneau**/
public class ClassNotFoundExceptionSimulator {private static final String CLASS_TO_LOAD = "org.ph.javaee.training5.ClassA";private static final int PROBLEM_SCENARIO = 1;/*** @param args*/public static void main(String[] args) {System.out.println("java.lang.ClassNotFoundException Simulator - Training 5");System.out.println("Author: Pierre-Hugues Charbonneau");System.out.println("http://javaeesupportpatterns.blogspot.com");switch(PROBLEM_SCENARIO) {// Scenario #1 - Class.forName()case 1:System.out.println("\n** Problem scenario #1: Class.forName() **\n");try {Class<?> newClass = Class.forName(CLASS_TO_LOAD);System.out.println("Class "+newClass+" found successfully!");} catch (ClassNotFoundException ex) {ex.printStackTrace();System.out.println("Class "+CLASS_TO_LOAD+" not found!");} catch (Throwable any) { System.out.println("Unexpected error! "+any);}break;// Scenario #2 - ClassLoader.loadClass()case 2:System.out.println("\n** Problem scenario #2: ClassLoader.loadClass() **\n"); try {ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Class<?> callerClass = classLoader.loadClass(CLASS_TO_LOAD);Object newClassAInstance = callerClass.newInstance();System.out.println("SUCCESS!: "+newClassAInstance);} catch (ClassNotFoundException ex) {ex.printStackTrace();System.out.println("Class "+CLASS_TO_LOAD+" not found!");} catch (Throwable any) { System.out.println("Unexpected error! "+any);}break;}System.out.println("\nSimulator done!");}
}
#ClassA
package org.ph.javaee.training5;/*** ClassA* @author Pierre-Hugues Charbonneau**/
public class ClassA {private final static Class<ClassA> CLAZZ = ClassA.class;static {System.out.println("Class loading of "+CLAZZ+" from ClassLoader '"+CLAZZ.getClassLoader()+"' in progress...");}public ClassA() {System.out.println("Creating a new instance of "+ClassA.class.getName()+"...");doSomething();}private void doSomething() { // Nothing to do...}
}
如果按原樣運行該程序,則每種情況的輸出如下:
#方案1輸出(基準)
java.lang.ClassNotFoundException
模擬器–訓練5
作者:Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com
**問題場景1:Class.forName()**
正在從ClassLoader'sun.misc.Launcher$AppClassLoader@bfbdb0'加載org.ph.javaee.training5.ClassA類。
成功找到類org.ph.javaee.training5.ClassA類!
模擬器完成!
#方案2輸出(基準)
java.lang.ClassNotFoundException
模擬器–訓練5
作者:Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com
**問題場景2:ClassLoader.loadClass()**
正在從ClassLoader'sun.misc.Launcher$AppClassLoader@2a340e'加載org.ph.javaee.training5.ClassA類的類…
正在創建org.ph.javaee.training5.ClassA的新實例…
成功!:org.ph.javaee.training5.ClassA@6eb38a
模擬器完成!
對于“基準”運行,Java程序能夠加載
A類
成功。
現在讓我們自愿更改的全名
A類
并針對每種情況重新運行該程序。 可以觀察到以下輸出:
#ClassA更改為ClassB
private static final String CLASS_TO_LOAD = "org.ph.javaee.training5.ClassB";
#方案1輸出(問題復制)
java.lang.ClassNotFoundException
模擬器–訓練5
作者:Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com
**問題場景1:Class.forName()**
java.lang.ClassNotFoundException
:org.ph.javaee.training5.ClassB
在java.net.URLClassLoader $ 1.run(
URLClassLoader.java:366
)
在java.net.URLClassLoader $ 1.run(
URLClassLoader.java:355
)
在java.security.AccessController.doPrivileged(
本機方法
)
在java.net.URLClassLoader.findClass(
URLClassLoader.java:354
)
在java.lang.ClassLoader.loadClass(
ClassLoader.java:423
)
在sun.misc.Launcher $ AppClassLoader.loadClass(
Launcher.java:308
)
在java.lang.ClassLoader.loadClass(
ClassLoader.java:356
)
在java.lang.Class.forName0(
本機方法
)
在java.lang.Class.forName(
Class.java:186
)
在org.ph.javaee.training5.ClassNotFoundExceptionSimulator.main(
ClassNotFoundExceptionSimulator.java:29
)
找不到org.ph.javaee.training5.ClassB類!
模擬器完成!
#方案2輸出(問題復制)
java.lang.ClassNotFoundException
模擬器–訓練5
作者:Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com
**問題場景2:ClassLoader.loadClass()**
java.lang.ClassNotFoundException
:org.ph.javaee.training5.ClassB
在java.net.URLClassLoader $ 1.run(
URLClassLoader.java:366
)
在java.net.URLClassLoader $ 1.run(
URLClassLoader.java:355
)
在java.security.AccessController.doPrivileged(
本機方法
)
在java.net.URLClassLoader.findClass(
URLClassLoader.java:354
)
在java.lang.ClassLoader.loadClass(
ClassLoader.java:423
)
在sun.misc.Launcher $ AppClassLoader.loadClass(
Launcher.java:308
)
在java.lang.ClassLoader.loadClass(
ClassLoader.java:356
)
在org.ph.javaee.training5.ClassNotFoundExceptionSimulator.main(
ClassNotFoundExceptionSimulator.java:51
)
找不到org.ph.javaee.training5.ClassB類!
模擬器完成!
發生了什么? 好吧,因為我們將完整的類名更改為org.ph.javaee.training5.ClassB,所以在運行時找不到此類(不存在),從而導致Class.forName()和ClassLoader.loadClass()調用均失敗。
您還可以通過將該程序的每個類打包到其自己的JAR文件中,然后從主類路徑中省略包含ClassA.class的jar文件來復制此問題。請嘗試一下并親自查看結果…(提示:NoClassDefFoundError)
現在,讓我們跳到解決策略。
java.lang。 ClassNotFoundException
:解決策略
現在您已經了解了這個問題,現在該解決它了。 解決方法可能非常簡單,也可能非常復雜,具體取決于根本原因。
- 不要太過復雜的根本原因,首先要排除最簡單的原因。
- 首先根據上述內容檢查java.lang.ClassNotFoundException堆棧跟蹤,并確定在運行時未正確加載哪個Java類,例如應用程序代碼,第三方API,Java EE容器本身等。
- 確定調用者,例如您在調用Class.forName()或ClassLoader.loadClass()之前從堆棧跟蹤中看到的Java類。 與第三方API相比,這將有助于您了解應用程序代碼是否出錯。
- 確定您的應用程序代碼是否未正確打包,例如,類路徑中缺少JAR文件
- 如果缺少的Java類不是來自您的應用程序代碼,請確定它是否屬于您正在按照Java應用程序使用的第三方API。 一旦識別出它,就需要將丟失的JAR文件添加到運行時類路徑或Web應用程序WAR / EAR文件中。
- 如果在多次解析嘗試后仍然掙扎,則可能意味著更復雜的類加載器層次結構問題。 在這種情況下,請查看我的NoClassDefFoundError文章系列,以獲取更多示例和解決方案
我希望本文能幫助您理解和重新了解這種常見的Java異常。
如果您仍在努力解決java.lang.ClassNotFoundException問題,請隨時發表任何評論或問題。
參考: java.lang.ClassNotFoundException:如何從Java EE支持模式和Java教程博客的JCG合作伙伴 Pierre-Hugues Charbonneau 解決 。
翻譯自: https://www.javacodegeeks.com/2012/11/java-lang-classnotfoundexception-how-to-resolve.html