类路径中存在Java类,但启动失败,错误为:无法找到或加载主类

类路径中存在Java类,但启动失败,错误为:无法找到或加载主类,java,jvm,classpath,classnotfoundexception,classloading,Java,Jvm,Classpath,Classnotfoundexception,Classloading,我有一个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

我有一个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
$ 
但是,如果我尝试使用类
栏中的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
不在类路径上。请注意,错误状态为“findloadmain class”。在
BarNotThere
的情况下,JVM实际上无法找到主类。但是在
Bar
情况下,它不能加载主类

为了完全加载一个类,JVM还需要每个超类对象的实例。在
Bar
的这个过程中,JVM尝试加载
ItemProcessor
的类对象。但是,由于该接口不在类路径上,加载主类
失败,启动终止,出现
错误:找不到或加载主类条

如果您难以找到有问题的类(因为没有消息这样说),可以使用
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
在这种情况下,可以在启动期间加载类
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
$

请注意,此问题部分包含在。我遇到了这个问题,并试图用这个问题来解决它。但一开始我无法解决它,因为超类不在类路径上的问题是一种边缘情况。这就是为什么我添加了这个特殊的案例作为一个新的Q/a。但是当出现
错误:找不到或加载主类栏
时,我怎么知道哪个类不在类路径上呢?@zczhuoho您可以使用
jdeps
工具来分析类路径。我会在答案中加上这个。
$ 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
$