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



我试图从命令行执行jar文件,仍然得到NoClassDefFoundError异常,但异常消息以" ... 13 more "结束。我猜意思是行。

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

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

您已经有了完整的堆栈跟踪。"... 13 more"消息是简单的抑制冗余/重复信息。

让我举例说明:

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 stackoverflow.Main.d(Main.java:11)
    at stackoverflow.Main.c(Main.java:10)
    at stackoverflow.Main.b(Main.java:9)
    at stackoverflow.Main.a(Main.java:8)
    at stackoverflow.Main.main(Main.java:6)
Caused by: java.lang.IllegalStateException: java.lang.UnsupportedOperationException: Test
    at stackoverflow.Main.g(Main.java:14)
    at stackoverflow.Main.f(Main.java:13)
    at stackoverflow.Main.e(Main.java:12)
    ... 5 more
Caused by: java.lang.UnsupportedOperationException: Test
    at stackoverflow.Main.j(Main.java:17)
    at stackoverflow.Main.i(Main.java:16)
    at stackoverflow.Main.h(Main.java:15)
    ... 8 more

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

如果没有抑制,输出将是:

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

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

如果你想解决你的NoClassDefFoundException,我们可能需要你的stacktrace。

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

如果你正在使用Maven来构建你的项目(或任何其他的构建工具,如Ivy, gradle,…),要小心所有添加到构建你的项目的传递依赖。

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

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

构建jar的方式在NoClassDefFoundError中发挥了作用。不打包依赖类的jar依赖于在运行时启动JVM时提供的这些依赖项。这些依赖项被称为运行时依赖项。另一种方法是将所有依赖类与正在构建的jar一起打包。这被称为Uber jar或者fat jar

NoClassDefFoundError发生时,特定的类文件没有在正在运行的jar中找到,也没有在启动JVM的类路径中找到所有可用的jar。您无法获得异常堆栈跟踪的原因是,这个错误甚至在ClassLoader加载类之前就发生了,因为在类路径中可用的jar中没有找到该类。

当jar是一个uber jar——它将所有依赖类捆绑到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>

最新更新