如何捕获java.lang.NoClassDefFoundError?

26

我制作了一个应用程序,它可以获取elf文件(*.a和*.o)并给出方法名称列表,但如果有人将任何文件重命名为*.a或*.o,则会显示:

Exception occurred during event dispatching:
java.lang.NoClassDefFoundError: org/eclipse/core/resources/IWorkspaceRunnable
    at org.eclipse.cdt.utils.AR.<init>(AR.java:237)
    at com.lge.windowELF.ElfBinaryArchive.<init>(ElfBinaryArchive.java:24)
    at com.lge.windowELF.ELFParserLibraryFile.createBinaryArchive(ELFParserLibraryFile.java:230)
    at com.lge.windowELF.ELFParserLibraryFile.<init>(ELFParserLibraryFile.java:46)
    at com.lge.windowELF.ELFWrapper.<init>(ELFWrapper.java:36)
    at com.lge.windowELF.ELF_UIIntegrated.actionPerformed(ELF_UIIntegrated.java:510)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)

在这种情况下,我想要显示一些警告消息。这个异常没有被try/catch捕获。


请寻找应包含IWorkspaceRunnable类或接口的JAR文件。它是否在您的类路径中存在? - S.L. Barth
可能是 当捕获 java.lang.Error 时机? 的重复问题。 - KV Prajapati
可以通过捕获特定的错误或“Throwable”来解决这个问题,但是你可能应该更优雅地处理代码中缺少文件的情况... - aishwarya
3个回答

78

NoClassDefFoundErrorError的子类而不是Exception。因此,您需要使用:

try {
  new org.eclipse.cdt.utils.AR();
}
catch(NoClassDefFoundError e) {
  //handle carefully
}

在你的代码中,注意不要捕获 Error 或者 Throwable。同时确保尽可能少地使用 catch 来包围代码,因为这个异常通常不应该被捕获。

更新:你确定要捕获这个异常吗?它非常罕见,我无法想象你想如何处理它。也许你应该将一个带有 IWorkspaceRunnable 类的 JAR 添加到你的 CLASSPATH 中?


6
这个答案更好,应该被接受,因为它确实回答了问题并帮助解决了实际问题。 - Mecki
1
可能会出现这样的情况,当您重新部署Web应用程序容器中的应用程序时。然后有一个会话销毁监听器,它试图查找一个不再在类路径上的类,因为它已被卸载。在这种情况下,您可能需要捕获它。 - ACV
这是一个情况:我在我的类路径中有所需的jar包,但我正在将代码分发给可能没有它的人,并希望确保他们知道如何在尝试运行它时添加它。 - Luke
@ACV 谢谢您解释为什么我会得到这个错误! - Noumenon
如果出于某种原因,您的捆绑包被移除或停用,这在OSGI / karaf中非常有用。但是,请小心处理。 - ssimm

5
不建议捕获 Error!JavaDoc指出:一个Error是Throwable的子类,表示应用程序不应该尝试捕获的严重问题。我的建议是先处理好NoClassDefFoundError,而不要担心代码抛出的异常。我宁愿在代码中,在ElfBinaryArchive构造器类上抛出一个InvalidELFFileException(基于合理猜测),或者包装这个类并在实例化时使用throws,这样如果有无效的ELF文件,就会抛出一个不错的异常。另外,确保将org.eclipse.core.resources.IWorkspaceRunnable放入CLASSPATH。

28
因为“应该不”与“绝不能”或“永远不”并不相同,下投反对票。应该不是指允许,只是不建议这么做。如果有人问“我该如何做某事?”,通常回答“不要这样做”并不会有太大帮助,甚至可能被视为粗鲁,即使你的回答可能有所帮助。 - Mecki
6
我从未知道我们会根据英语使用情况进行投票。我认为SO是基于编程相关解决方案的。如果这是基于英语语言的,那么这篇文章不应该更有益于英语StackExchange吗?(参见示例)。 - Buhake Sindi
2
当用户询问您如何做某事时,您告诉他不应该这样做,这就是为什么您被踩了。"你不应该这样做"并不是对问题的回答。 - Mecki
1
告诉他不应该做并不能回答如何做的问题。问题仍然是:如何捕捉java.lang.NoClassDefFoundError? 你到底在哪里回答了这个问题?你__没有__。如果我不知道如何做到这一点,读完你的答案后我仍然不会知道它。 - Mecki
1
你可以整天和我争论,事实不会改变。你没有回答问题,句号。你的回答中没有任何部分展示如何捕获异常,而那正是问题所在,句号。Tomasz Nurkiewicz已经回答了这个问题,展示了一个捕获异常的try块(__那__才是问题的正确答案,没有别的)。我标记了你的回答为“不是答案”。现在停止这个愚蠢的讨论吧,这是浪费时间,因为我不会撤回我的点踩;尽管助人为乐是一回事,但回答问题是另外一回事。 - Mecki
显示剩余7条评论

0

我只是想回答一下,关于不建议捕获这个错误的问题。我认为在适当的情况下,以正确的方式进行捕获是可以的。我可以想到几种情况下它是有意义的:

  • 如果你的应用程序依赖于最终用户提供的某些依赖项
  • 某些依赖项由另一个应用程序预先安装
  • 你只是想给出一个更清晰的错误消息并退出

对我来说,这是非常常见的情况,我提供一个应用程序,运维团队提供环境。如果某些依赖项不存在,我会记录一个错误,说明该功能不存在,但我的应用程序仍然继续运行。

我还要补充的是,在catch块中,你需要确保你使用的依赖项已经确认存在。这并不难,例如,如果你需要一个用于日志记录的jar包,并且你之前在代码中成功使用过它,那么就没问题了。如果日志记录的依赖项不存在,那么你的代码根本不可能执行到那一步。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接