3年前 (2021-02-18)  Java系列 |   抢沙发  1002 
文章评分 0 次,平均分 0.0

NoClassDefFoundError和ClassNotFoundException的区别

在本文中,我们将了解NoClassDefFoundErrorClassNotFoundException之间的区别。这是增加java异常知识的问题之一。

我们将研究NoClassDefFoundErrorClassNotFoundException的区别、相似性和示例。

NoClassDefFoundErrorClassNotFoundException之间的差异

Error与Exception:主要区别在于它们的名称。您可以看到NoClassDefFoundError是Error,它是从LinkageError派生的。这意味着NoClassDefFoundError在链接过程中发生,程序无法运行,但编译成功

ClassNotFoundException是从ReflectiveOperationException派生的异常,它发生在运行时。

不可恢复vs可恢复NoClassDefFoundError指try/catch/finally块未处理的不可恢复情况。ClassNotFoundException是选中的异常,需要使用try/catch/finally块进行处理。

抛出时的情况以及如何避免这些情况:出现ClassNotFoundException时的情况是应用程序试图通过其字符串名称在类中加载,使用:

  • 类中的forName方法;
  • 类装入器中的findSystemClass方法;
  • 类装入器中的loadClass方法;

但找不到具有指定名称的类的定义。

为避免此异常,需要确保:

  • 类在与该类关联的类装入器的逻辑类路径中可用;
  • 类加载器API是否正确使用Class.forName();
  • 被加载的类的依赖类对类加载器可见;
  • 等。

出现NoClassDefFoundError时的情况是Java虚拟机或ClassLoader实例试图加载类的定义(作为普通方法调用的一部分或使用新表达式创建新实例的一部分),但找不到类的定义(类的格式不正确,类的版本号不匹配等)。

类无法加载,原因如下:

  • 未能加载依赖类;
  • 依赖类格式错误;
  • 类的版本号不正确;
  • 类已经加载到另一个类加载器中;
  • 等。

NoClassDefFoundError和ClassNotFoundException示例

如果我们有以下代码:

public class NoClassDefFoundErrorExample {
    public static void main(String[] args) {
        A a = new A(); 
    }
}
public class A extends B {
}

public class B {
}

现在如果我们从类路径编译后删除B.class

执行此代码的结果是:线程“main”中出现异常java.lang.NoClassDefFoundError: B

如下图所示:

NoClassDefFoundError和ClassNotFoundException的区别

public class ClassNotFoundExceptionExample {
    public static void main(String[] args) throws ClassNotFoundException {
        Class.forName("com.example.Class1");
    }
}

执行此代码的结果是:

线程“main”中出现异常java.lang.ClassNotFoundException: com.example.Class1

因为类加载器无法加载com.example.Class1类。

NoClassDefFoundError和ClassNotFoundException的区别

概述:ClassNotFoundException和NoClassDefFoundError之间的区别

ClassNotFoundException NoClassDefFoundError
Exception vs Error CheckedException Error
抛出阶段 运行时 链接
派生 ReflectiveOperationException LinkageError
不可恢复vs可恢复 可恢复 不可恢复
需要try/catch/finally块
抛出异常场景

应用程序试图加载到类中通过它的字符串名,但不是具有指定找不到名称

ClassLoader实例尝试加载在类的定义中找不到类的定义

总结:

如果我们看看oracle文档http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html,我们可以发现:

如果在类加载期间发生错误,则LinkageError子类的实例必须在程序中(直接或间接)使用被加载的类或接口的某个点抛出。

如果Java虚拟机曾经尝试在验证或解析(而不是初始化)期间加载类C,并且用于启动C加载的类加载器抛出ClassNotFoundException实例,则Java虚拟机必须抛出NoClassDefFoundError实例,其原因是ClassNotFoundException的实例。

从这个解释我们可以得出这样的结论:ClassNotFoundExceptionNoClassDefFoundError的根本原因,而NoClassDefFoundError是类型加载错误的一个特例,发生在链接步骤。

 

除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/1534.html

关于

发表评论

表情 格式

暂无评论

登录

忘记密码 ?

切换登录

注册