17

当我运行此代码时,应用程序以 ClassNotFoundException 退出:

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

当我尝试编译此代码时,编译器抱怨 ClassNotFoundException 不可访问,因为它不是从 try-catch 语句的 try 子句中抛出的。

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

当我运行这段代码时,唯一被捕获的是 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());
}

以下代码将编译并捕获错误(并且只有错误),但它很笨拙:

//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");
}

然而,当我编写以下内容时,我可以在没有 catch 子句的情况下摆脱错误原因:

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

示例 3 会让我得出结论,throwable 是 NoClassDefFoundError。示例 1 会让我得出结论,throwable 是 ClassNotFoundException。然而,示例 2 表明 java 甚至不允许我编写代码来正确捕获 ClassNotFoundException。

就在我即将断定这里的问题是由异常引起的错误时,我运行了前面示例中显示的代码,这表明这不是规则。

有人可以解释一下这里发生了什么吗?

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
4

5 回答 5

12

所以,你误解了你的堆栈跟踪。

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

您的代码正在生成一个NoClassDefFoundError. 根本原因ClassNotFoundException是一个。请记住,这cause是 Throwable 类的一个属性,并且在打印堆栈跟踪时,Java 将显示有关直接异常及其潜在原因的信息。很难说为什么该define方法在内部失败,但可以肯定的是 - 您不能package在包名称中使用关键字。

于 2013-04-02T03:10:09.337 回答
7

NoClassDefFoundError 在找到类的 .class 时发生,但无法从该 .class 构造该类。

有几种不同的场景经常发生,还有一些更晦涩的场景。

  • .class 文件包含与类文件名/包不匹配的名称(和包)
  • 找不到验证和初始化类所需的类
  • 类初始化期间发生错误

在这些场景中的大多数情况下,还有一个更早发生的错误或异常,被类加载器捕获,并发出新错误信号。

目前尚不清楚上述异常回溯中究竟发生了哪种情况,但我猜测某种名称不匹配。

于 2013-04-02T02:41:30.543 回答
2

NoClassDefFoundError实际上是一个子类,Error这些不应该被捕获。有关详细信息,请参阅错误的文档。以下重要说明:

Error 是 Throwable 的子类,表示合理的应用程序不应尝试捕获的严重问题。大多数此类错误是异常情况。

方法不需要在其 throws 子句中声明任何可能在方法执行期间抛出但未被捕获的 Error 子类,因为这些错误是不应该发生的异常情况。

出于这个原因,我认为你应该仔细看看你的代码,看看你做错了什么。

于 2013-04-02T02:02:53.787 回答
0
//and yet this works just fine...
try
{
    throw new Error(new IOException());
}
catch (Error e)
{
    System.out.println("err");
}

将其替换为:

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

试试 e.printStackTrace() 你会看到类似的输出。

于 2013-09-17T14:22:34.647 回答
-1

正如已经指出的那样,Java 不允许您处理错误。

无论如何,我不确定您尝试解决这些异常(和错误)的原因是什么,但这些是程序员并不真正需要担心的事件(大多数时候)。对我来说,这是您的代码/项目中其他地方存在问题的症状。如果系统抛出 a ClassNotFoundException,并且它允许您捕获它,您将如何处理它?还是您更愿意解决应用程序所需的某个类不在类路径中的实际问题?

此外,您可能需要检查NoClassDefFoundError 和 ClassNotFoundException 之间的区别,以更好地解决您的问题。

于 2013-04-02T02:15:50.347 回答