简体   繁体   English

如果NoClassDefFoundError是由ClassNotFoundException引起的,为什么Java期望你捕获两个throwable?

[英]If a NoClassDefFoundError is caused by a ClassNotFoundException, why does Java expect you to catch both throwables?

When I run this code the app exits with a ClassNotFoundException: 当我运行此代码时,应用程序退出时出现ClassNotFoundException:

//uncaught ClassNotFoundException
try
{
    Class<?> clazz = defineClass(null, bytes, 0, bytes.length, null);
    table.put(clazz.getName(), clazz);
}
catch (NoClassDefFoundError e)
{
}

When I attempt to compile this code, the compiler complains that the ClassNotFoundException is not reachable because it is not thrown from within the try-clause of the try-catch statement. 当我尝试编译此代码时,编译器会抱怨ClassNotFoundException无法访问,因为它不会从try-catch语句的try-clause中抛出。

//Won't compile
try
{
    Class<?> clazz = defineClass(null, bytes, 0, bytes.length, null);
    table.put(clazz.getName(), clazz);
}
catch (ClassNotFoundException e)
{
}

When I run this code, the only throwable that is caught is a NoClassDefFoundError. 当我运行此代码时,捕获的唯一throwable是NoClassDefFoundError。

//catches throwable of type java.lang.NoClassDefFoundError,
//with a java.lang.ClassNotFoundException as its cause
try
{
    Class<?> clazz = defineClass(null, bytes, 0, bytes.length, null);
    table.put(clazz.getName(), clazz);
}
catch (Throwable e)
{
    System.out.println(e.getClass().getName());
    System.out.println(e.getCause().getClass().getName());
}

The following code will compile and catch the error (and only the error), but it's clumsy: 下面的代码将编译并捕获错误(并且只有错误),但它很笨拙:

//possible workaround
try
{
    Class<?> clazz = defineClass(null, bytes, 0, bytes.length, null);
    table.put(clazz.getName(), clazz);
    if (1 == 0) throw new ClassNotFoundException(); // we want the code to compile
}
catch (ClassNotFoundException e)
{
    System.out.println("ex");
}
catch (NoClassDefFoundError e)
{
    System.out.println("err");
}

And yet when I write the following, I can get away without a catch clause for the cause of the error: 然而,当我编写以下内容时,我可以在没有catch子句的情况下逃避错误原因:

//and yet this works just fine...
try
{
    throw new Error(new IOException());
}
catch (Error e)
{
    System.out.println("err");
}

Example 3 would lead me to conclude that the throwable was a NoClassDefFoundError. 示例3将使我得出结论,throwable是NoClassDefFoundError。 Example 1 would lead me to conclude that the throwable was a ClassNotFoundException. 示例1将使我得出结论,throwable是ClassNotFoundException。 And yet, Example 2 shows that java won't even let me write code to properly catch the ClassNotFoundException. 然而,示例2显示java甚至不会让我编写代码来正确捕获ClassNotFoundException。

Just when I was about to conclude that the problem here is the error-caused-by-an-exception, I ran the code shown in the previous example which shows that that is not the rule. 正当我即将得出结论,这里的问题是由异常引起的错误时,我运行了上一个示例中显示的代码,该代码表明这不是规则。

Can someone please explain what's going on here? 有人可以解释一下这里发生了什么吗?

PS: this is the stack trace: PS:这是堆栈跟踪:

 java.lang.NoClassDefFoundError: com/my/pckage/MyClass
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at Main$MyClassLoader.getClasses(Main.java:78)
at Main.main(Main.java:109)
 Caused by: java.lang.ClassNotFoundException: com.my.pckage.MyClass
at java.lang.ClassLoader.findClass(ClassLoader.java:522)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 4 more

So, you are misunderstanding your stack trace. 所以,你误解了你的堆栈跟踪。

java.lang.NoClassDefFoundError: com/my/package/MyClass
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
    at Main$MyClassLoader.getClasses(Main.java:78)
    at Main.main(Main.java:109)
Caused by: java.lang.ClassNotFoundException: com.my.package.MyClass

Your code is generating a NoClassDefFoundError . 您的代码生成NoClassDefFoundError The underlying cause is a ClassNotFoundException . 根本原因ClassNotFoundException Remember that cause is a property of the Throwable class, and that when printing stacktraces, Java will display information both on the direct exception and its underlying cause(s). 请记住, cause是Throwable类的属性,并且在打印堆栈跟踪时,Java将显示有关直接异常及其根本原因的信息。 It's tougher to say why the define method is failing internally, but one thing is for sure - you cannot use the keyword package in a package name. 更难说为什么define方法在内部失败,但有一点是肯定的 - 你不能在包名中使用关键字package

NoClassDefFoundError occurs when the .class for a class is found, but the class cannot be constructed from that .class. 找到类的.class时会发生NoClassDefFoundError,但无法从该.class构造类。

There are several different scenarios that occur commonly, plus a few more obscure ones. 通常会出现几种不同的情况,加上一些比较模糊的情景。

  • The .class file contains a name (and package) that does not match the class file name/package .class文件包含与类文件名/包不匹配的名称(和包)
  • A class that was needed to verify and initialize the class could not be found 找不到验证和初始化类所需的类
  • An error occurred during class initialization 类初始化期间发生错误

In most of these scenarios there is another error or exception that occurs earlier, is caught by the class loader, and the new error is signaled. 在大多数情况下,先前发生的另一个错误或异常会被类加载器捕获,并且会发出新错误信号。

It's not clear exactly which scenario is occurring in the above exception traceback, but I'm guessing some sort of name mismatch. 目前尚不清楚上述异常追溯中究竟出现了哪种情况,但我猜测某种名称不匹配。

NoClassDefFoundError is actually a subclass of Error and these should not be caught. NoClassDefFoundError实际上是Error的子类,不应该捕获它们。 See the docs of Error for details. 有关详细信息,请参阅错误文档 The important note below: 以下重要说明:

An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Error是Throwable的子类,表示合理的应用程序不应该尝试捕获的严重问题。 Most such errors are abnormal conditions. 大多数此类错误都是异常情况。

A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur. 一个方法不需要在其throws子句中声明在执行方法期间可能抛出但未捕获的任何Error类,因为这些错误是永远不应发生的异常情况。

For this reason, I think you should take a closer look at your code to see what you are doing wrong. 出于这个原因,我认为你应该仔细看看你的代码,看看你做错了什么。

//and yet this works just fine...
try
{
    throw new Error(new IOException());
}
catch (Error e)
{
    System.out.println("err");
}

Replace it with: 替换为:

//and yet this still works fine...
try
{
    throw new NoClassDefFoundError(new ClassNotFoundException());
}
catch (Error e)
{
    System.out.println("err");
}

Try a e.printStackTrace() and you'll see a similar output. 尝试e.printStackTrace(),你会看到类似的输出。

As has been pointed out already, Java won't allow you to handle errors. 正如已经指出的那样,Java不允许您处理错误。

Anyway, I'm not really sure what your reasons are for trying to work around these exceptions (and errors) but these are occurrences that programmers don't really need to worry about (most of the time). 无论如何,我不确定你尝试解决这些异常(和错误)的原因是什么,但这些都是程序员并不需要担心的事情(大多数时候)。 To me this is a symptom that there is a problem elsewhere in your code/project. 对我而言,这是您的代码/项目中其他地方存在问题的症状。 If the system throws a ClassNotFoundException , and it allows you to catch it, how would you handle it? 如果系统抛出ClassNotFoundException ,它允许你捕获它,你将如何处理它? Or would you rather address the actual problem that a certain class required by your application is not in the classpath? 或者您是否愿意解决应用程序所需的某个类不在类路径中的实际问题?

Also, you may want to check the difference between NoClassDefFoundError and ClassNotFoundException to better address your problem. 此外,您可能需要检查NoClassDefFoundError和ClassNotFoundException之间区别,以更好地解决您的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么捕获Throwables时会捕获Java中的异常? - Why catch Exceptions in Java, when you can catch Throwables? 难道NoClassDefFoundError总是有ClassNotFoundException引起的吗? - Does NoClassDefFoundError have always ClassNotFoundException in caused by? 由java.lang.NoClassDefFoundError和ClassNotFoundException引起的错误 - Error caused by java.lang.NoClassDefFoundError and ClassNotFoundException NoClassDefFoundError:…由ClassNotFoundException引起 - NoClassDefFoundError: … Caused by ClassNotFoundException ClassNotFoundException 导致的线程“主”java.lang.NoClassDefFoundError 中的异常 - Exception in thread "main" java.lang.NoClassDefFoundError caused by ClassNotFoundException 将 Java Web 应用程序部署到 Heroku:由 ClassNotFoundException 引起的 NoClassDefFoundError - deploying java web app to heroku: NoClassDefFoundError caused by ClassNotFoundException NoClassDefFoundError原因:java.lang.ClassNotFoundException:junit.textui.ResultPrinter - NoClassDefFoundError Caused by: java.lang.ClassNotFoundException: junit.textui.ResultPrinter loadClass抛出由ClassNotFoundException引起的NoClassDefFoundError - loadClass throws NoClassDefFoundError caused by ClassNotFoundException 如何解决ClassNotFoundException引起的NoClassDefFoundError? - How to solve a NoClassDefFoundError caused by ClassNotFoundException? 为什么发生InflateException(由ClassNotFoundException引起)? - Why does an InflateException (Caused by ClassNotFoundException) occur?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM