[英]Java class is present in classpath but startup fails with Error: Could not find or load main class
我有一個jar文件foobar.jar
其中包含以下兩個類:
public class Foo {
public static void main(String[] args) {
System.out.println("Foo");
}
}
另一個類如下所示:
import javax.batch.api.chunk.ItemProcessor;
public class Bar implements ItemProcessor {
public static void main(String[] args) {
System.out.println("Bar");
}
@Override
public Object processItem(Object item) throws Exception {
return item;
}
}
如果我使用以下命令執行該程序,則該程序將按預期方式運行並顯示Foo
:
$ java -cp foobar.jar Foo
Foo
$
但是,如果我嘗試使用Bar
類中的main方法來啟動程序,則JVM將顯示啟動錯誤並退出:
$ java -cp foobar.jar Bar
Error: Could not find or load main class Bar
$
這與我嘗試使用不在jar中的類來嘗試啟動程序的錯誤相同,例如
$ java -cp foobar.jar BarNotThere
Error: Could not find or load main class BarNotThere
$
為什么會出現此錯誤? Foo.main
方法可以啟動並且我可以從jar中反編譯Bar
類這一事實證明,該類應該在類路徑上可用。 我意識到這可能與ItemProcessor
接口不在類路徑上有關。 但是在那種情況下我不應該得到java.lang.ClassNotFoundException
嗎?
問題確實是接口ItemProcessor
不在類路徑上。 請注意,錯誤狀態為“ 查找或加載主類”。 在BarNotThere
的情況下,JVM確實無法找到主類。 但是在Bar
情況下,它無法加載主類。
為了完全加載類,JVM還需要每個超類對象的實例。 在Bar
此過程中,JVM嘗試加載ItemProcessor
的類對象。 但是,因為此接口不在類路徑上,所以主類Bar
加載失敗,並且啟動因Error: Could not find or load main class Bar
終止。
如果您在尋找有問題的類時遇到困難(因為沒有消息這樣說),則可以使用jdeps
工具檢查類路徑。 只需使用相同的類路徑,但運行jdeps
而不是java
:
$ jdeps -cp foobar.jar Bar
foobar.jar -> java.base
foobar.jar -> not found
<unnamed> (foobar.jar)
-> java.io
-> java.lang
-> javax.batch.api.chunk not found
(這是使用openjdk-9創建的,實際輸出可能會有所不同,具體取決於Java版本)
這應該為您提供足夠的提示,以指示在哪里尋找缺失的班級。
進一步說明
注意加載和初始化類之間的區別。 如果初始化期間類加載失敗(這意味着已成功找到並加載該類),則將獲得預期的ClassNotFoundException
。 請參見以下示例:
import javax.batch.api.chunk.ItemProcessor;
public class FooBar {
private static ItemProcessor i = new ItemProcessor() {
@Override
public Object processItem(Object item) throws Exception {
return item;
}
};
public static void main(String[] args) {
System.out.println("Foo");
}
}
在這種情況下,可以在啟動期間加載FooBar
類。 但是它無法初始化,因為靜態字段i
需要ItemProcessor
類,該類不在類路徑中。 如果在類上執行靜態方法,則初始化是前提條件,在這種情況下,JVM嘗試調用main
方法。
$ java -cp foobar.jar FooBar
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: javax/batch/api/chunk/ItemProcessor
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: javax.batch.api.chunk.ItemProcessor
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
$
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.