从带有完整异常消息的命令行执行 jar

executing jar form commandline with full exception message

我正在尝试从命令行执行 jar 文件,但仍然收到 NoClassDefFoundError 异常,但异常消息以“... 13 more”结尾。我猜是指台词。

那么如何从命令提示符中获取完整的异常消息呢?我正在使用 IntelliJ 14 作为开发环境,但调试和编译没有显示任何错误并成功结束。 (这是神器构建)

我什至试图将该错误消息写入 try/catch 块中的文件,但我的猜测是这发生在主要方法代码执行之前,因为没有创建文件或 System.out.println() 没有已执行。

如果您想要解决您的 NoClassDefFoundException,我们可能需要您的堆栈跟踪。

通常当您从命令行执行时抛出 NoClassDefFoundException 是由于您的类路径定义错误(-cp 参数在您的 java -cp list_of_jars package.MainClass ).

如果您正在使用 Maven 来构建您的项目(或任何其他构建工具,例如 Ivy,gradle,...),请注意为构建您的项目而添加的所有传递依赖项.

例如,如果您的项目依赖于 myLib1.jar,但 myLib1 依赖于 myLib2.jar,您必须执行 java -cp /myLib1.jar:/myLib2.jar:/myProject.jar mypackage.MyMainClass。

好吧,为了获得更多帮助,我们需要您的异常的堆栈跟踪、您的命令行和您的 Maven POM 部分(如果您使用的是 Maven)(或者提供给您的构建工具的已声明依赖项的列表)

构建 jars 的方式在 NoClassDefFoundError 中扮演着重要角色。 不打包依赖项 classes 的 jar 依赖于在 JVM 启动时 运行 时提供的这些依赖项。这些依赖性称为 运行 时间依赖性 。 另一种方法是将所有依赖的 classes 与正在构建的 jar 一起打包。这有时称为 Uber jarfat jar

NoClassDefFoundError 当在 运行 的 jar 以及启动 JVM 的 class 路径中的所有可用 jar 中找不到特定的 class 文件时发生。您无法获得异常堆栈跟踪的原因是因为此错误甚至在 ClassLoader 加载 class 之前发生,因为 class 在 [=29= 中可用的 jars 中找不到]路径。

当 jar 是 uber jar - 将所有依赖项 class 捆绑到 jar 中时,不应抛出此异常。

如果使用 Maven 来构建项目,这里是一个如何使用 Maven Assembly Plugin 构建 uber jar 的示例。

    <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>fully qualified name of the main class </mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>install</phase>
                        <goals>
                            <goal>attached</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>

您已经有了完整的堆栈跟踪。 “... 13 more”消息很简单,可以抑制 redundant/repeated 信息。

让我举例说明:

public static void main(String[] args) throws Exception { a(); }
private static void a() { b(); }
private static void b() { c(); }
private static void c() { d(); }
private static void d() { try { e(); } catch (Exception e) { throw new RuntimeException(e); } }
private static void e() { f(); }
private static void f() { g(); }
private static void g() { try { h(); } catch (Exception e) { throw new IllegalStateException(e); } }
private static void h() { i(); }
private static void i() { j(); }
private static void j() { throw new UnsupportedOperationException("Test"); }

此代码在调用堆栈深处引发异常。异常被捕获并包裹在其他异常中,因此输出将是:

Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalStateException: java.lang.UnsupportedOperationException: Test
    at Whosebug.Main.d(Main.java:11)
    at Whosebug.Main.c(Main.java:10)
    at Whosebug.Main.b(Main.java:9)
    at Whosebug.Main.a(Main.java:8)
    at Whosebug.Main.main(Main.java:6)
Caused by: java.lang.IllegalStateException: java.lang.UnsupportedOperationException: Test
    at Whosebug.Main.g(Main.java:14)
    at Whosebug.Main.f(Main.java:13)
    at Whosebug.Main.e(Main.java:12)
    ... 5 more
Caused by: java.lang.UnsupportedOperationException: Test
    at Whosebug.Main.j(Main.java:17)
    at Whosebug.Main.i(Main.java:16)
    at Whosebug.Main.h(Main.java:15)
    ... 8 more

IllegalStateException 调用堆栈抑制的 5 行与 RuntimeException 调用堆栈中的行相同。
UnsupportedOperationException 调用堆栈抑制的 8 行与其他两个调用堆栈中的行相同。

没有抑制,输出将是:

Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalStateException: java.lang.UnsupportedOperationException: Test
    at Whosebug.Main.d(Main.java:11)
    at Whosebug.Main.c(Main.java:10)
    at Whosebug.Main.b(Main.java:9)
    at Whosebug.Main.a(Main.java:8)
    at Whosebug.Main.main(Main.java:6)
Caused by: java.lang.IllegalStateException: java.lang.UnsupportedOperationException: Test
    at Whosebug.Main.g(Main.java:14)
    at Whosebug.Main.f(Main.java:13)
    at Whosebug.Main.e(Main.java:12)
    at Whosebug.Main.d(Main.java:11)
    at Whosebug.Main.c(Main.java:10)
    at Whosebug.Main.b(Main.java:9)
    at Whosebug.Main.a(Main.java:8)
    at Whosebug.Main.main(Main.java:6)
Caused by: java.lang.UnsupportedOperationException: Test
    at Whosebug.Main.j(Main.java:17)
    at Whosebug.Main.i(Main.java:16)
    at Whosebug.Main.h(Main.java:15)
    at Whosebug.Main.g(Main.java:14)
    at Whosebug.Main.f(Main.java:13)
    at Whosebug.Main.e(Main.java:12)
    at Whosebug.Main.d(Main.java:11)
    at Whosebug.Main.c(Main.java:10)
    at Whosebug.Main.b(Main.java:9)
    at Whosebug.Main.a(Main.java:8)
    at Whosebug.Main.main(Main.java:6)

这只是大量无用的冗余输出浪费,在调用堆栈更深的实际应用程序中会变得更糟。