调用Exception.printStackTrace时的AbstractMethodError

时间:2011-07-21 14:30:08

标签: java exception abstract

在catch子句中,我想打印异常的strack跟踪:

try {
    ...
} catch (Exception exc) {
    exc.printStackTrace();
    ...
}

但在某些情况下,我没有获得堆栈跟踪,而是看到类似这样的内容:

Exception in thread "pool-1-thread-2" java.lang.AbstractMethodError: java.lang.Exception.printStackTrace()V
    ...

通常,如果库在运行时与编译时的版本不同,则会发生此异常,但在这种情况下,我使用Java库中的类。 printStackTrace是在Throwable中实现的,因此这个方法在Exception或任何派生类中都不能是抽象的。此外,并不总是抛出此AbstractMethodError,有时在此特定catch子句中还有其他异常(程序流依赖于文件中的数据和当前时间,因此有时会发生其他事情,如我自己的代码中抛出的ArrayIndexOutOfBoundsExceptions或IllegalStateExceptions并且我希望而不是奇怪的错误。)

所以,问题是:如何发生特定的AbstractMethodError?

PS:我在Linux上使用Eclipse Helios并使用JDK 1.6.0_24作为运行时环境来启动我的应用程序。

编辑:有一个错字(printStrackTrace),我纠正了它。只是写在我的脑海里,与我的问题没有任何关系。它(或应该是)独立的应用程序,没有Web应用程序,没有Eclipse RCP应用程序,只是一个普通的旧Java应用程序(或多或少)。问题确实发生在另一台计算机上 - 也可以使用Eclipse Helios,也可以使用Fedora Linux,但使用JDK 1.6.0_21。

令我惊讶的是,确实可以调用getClass().getName()(但我没有尝试过其他方法),例外类型为java.lang.ArrayIndexOutOfBoundsException。我只是尝试使用OpenJDK 1.6.0(因为它已经安装在我的系统上)并得到了不同的结果。而不是抛出AbstractMethodErrorprintStackTrace只打印一个空行而getMessage()返回null(而不是抛出错误)。所以我不知道抛出异常的确切位置,因为层次结构中的try-catch-block捕获异常只是为了优雅地停止应用程序的一部分。我可能会在某些方面捕获这种异常类型,以便了解它的来源。但这并不能解释异常本身的奇怪行为。

编辑2:最后我追踪了问题。事实证明这是我昨天在同一条线上发生的一个例外,但有时异常本身表现得很奇怪。我在get(int)(更确切地说是使用List包装的ArrayList)上使用Collections.unmodifiableList(List)的索引(即初始值)调用-1 ,在一个循环内,这个索引应该改变,但不会出于任何原因)。至少现在我知道在哪里修复ArrayIndexOutOfBoundsException,但我仍然不知道为什么异常本身就很奇怪。

修改3 :我尝试了Throwable.class.getMethod("printStackTrace").invoke(exc);而不是exc.printStackTrace();并获得java.lang.NoSuchMethodError: java.lang.Throwable.printStackTrace()V而不是java.lang.AbstractMethodError。我还尝试使用javacjar从shell编译java文件(只有异常来自的一个库,因为手动编译所有jar会很繁琐)。结果是一样的。如果我在该行抛出一个IndexArrayOutOfBoundsException,那么堆栈跟踪将被打印得很好。也许我不得不希望这个问题非常罕见,并且永远不会发生在其他任何地方。

1 个答案:

答案 0 :(得分:2)

据我了解,您已在Eclipse Helios中启动了应用程序。这可能是因为Eclipse与OSGi和专用类加载器的模块化:用于运行应用程序的ClassLoader层次结构可能导致无效的链接。它主要取决于涉及的异常类以及您在应用程序类路径中包含的jar文件 - 您自己的jar中的一个可能与Eclipse本身使用的jar文件冲突。您可以提供其他详细信息吗?

我猜你用“java应用程序”运行配置启动它。您是否选中了“包含系统库”或“包含的继承主”或其他任何选项之一?

顺便说一句,您的应用程序最终将作为一个独立的Java虚拟机运行,它应该在该环境中运行良好。

如果不是这种情况,运行带有-verbose:class命令行选项的java应用程序并在崩溃之前检查输出中的最新行,您可能会得到关于冲突库的线索(在运行时与编译时不同) -time)。