写点什么

NoClassDefFoundError 和 ClassNotFoundException 有什么区别

作者:共饮一杯无
  • 2023-04-16
    浙江
  • 本文字数:1782 字

    阅读完需:约 6 分钟

NoClassDefFoundError 和 ClassNotFoundException 有什么区别



从类继承层次上来看,ClassNotFoundException 是从 Exception 继承的,所以 ClassNotFoundException 是一个检查异常。NoClassDefFoundError 是从 Error 继承的。和 ClassNotFoundException 相比,明显的一个区别是,NoClassDefFoundError 并不需要应用程序去关心 catch 的问题。

NoClassDefFoundError

当 JVM 在加载一个类的时候,如果这个类在编译时是可用的,但是在运行时找不到这个类的定义的时候,JVM 就会抛出一个 NoClassDefFoundError 错误。比如当我们在 new 一个类的实例的时候,如果在运行时类找不到,则会抛出一个 NoClassDefFoundError 的错误。通常发生在执行动态代码块或者初始化静态字段时报了异常,从而导致类初始化失败而引发 NoClassDefFoundError。案例如下:


public class ClassWithInitErrors {    static int data = 1 / 0;}
public class NoClassDefFoundErrorTest { public ClassWithInitErrors getClassWithInitErrors() { ClassWithInitErrors test = new ClassWithInitErrors(); return test; }
@Test(expected = NoClassDefFoundError.class) public void givenInitErrorInClass_whenloadClass_thenNoClassDefFoundError() { NoClassDefFoundErrorTest sample = new NoClassDefFoundErrorTest(); sample.getClassWithInitErrors(); }}
复制代码


执行程序后会出现如下错误:


java.lang.Exception: Unexpected exception, expected<java.lang.NoClassDefFoundError> but was<java.lang.ExceptionInInitializerError>
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) ... moreCaused by: java.lang.ArithmeticException: / by zero at com.zjq.dailyrecord.throwable.ClassWithInitErrors.<clinit>(ClassWithInitErrors.java:4) ... 25 more
复制代码

ClassNotFoundException

当应用程序运行的过程中尝试使用类加载器去加载 Class 文件的时候,如果没有在 classpath 中查找到指定的类,就会抛出 ClassNotFoundException。一般情况下,当我们使用 Class.forName()或者 ClassLoader.loadClass 以及使用 ClassLoader.findSystemClass()在运行时加载类的时候,如果类没有被找到,那么就会导致 JVM 抛出 ClassNotFoundException。最简单的,当我们使用 JDBC 去连接数据库的时候,我们一般会使用 Class.forName()的方式去加载 JDBC 的驱动,如果我们没有将驱动放到应用的 classpath 下,那么会导致运行时找不到类,所以运行 Class.forName()会抛出 ClassNotFoundException。案例如下:


public class ClassNotFoundExceptionTest {    public static void main(String[] args) {        try {            Class.forName("com.mysql.jdbc.Driver");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }    }}
复制代码


执行后输出:


java.lang.ClassNotFoundException: com.mysql.jdbc.Driver  at java.net.URLClassLoader.findClass(URLClassLoader.java:381)  at java.lang.ClassLoader.loadClass(ClassLoader.java:424)  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)  at java.lang.ClassLoader.loadClass(ClassLoader.java:357)  at java.lang.Class.forName0(Native Method)  at java.lang.Class.forName(Class.java:264)  at com.zjq.dailyrecord.throwable.ClassNotFoundExceptionTest.main(ClassNotFoundExceptionTest.java:6)
复制代码

总结区别

解决办法

他们的主要原因是运行时类路径中类文件不可用。下面是几点具体的原因:


  1. 排查所需的 jar 包是否在类路径中,如果没有就添加进去。

  2. 如果发现类在 classpath 里面,很有可能是 classpath 被重写了,需要再次确定应用准确的 classpath

  3. 依赖包发生了冲突,比如应该依赖高版本 jar 包,但又其它包传递依赖了低版本 jar 包,导致高版本中某些类找不到。

  4. 如果应用中用到了多个类加载器,一个类加载器加载的类,无法再其他的类加载器中使用。


本文内容到此结束了,

如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。

如有错误❌疑问💬欢迎各位大佬指出。

主页共饮一杯无的博客汇总👨‍💻

保持热爱,奔赴下一场山海。🏃🏃🏃

发布于: 刚刚阅读数: 3
用户头像

鲜衣怒马意气风发,愿你归来仍是少年。 2018-10-19 加入

全栈开发者,CSDN博客专家,51CTO 专家博主,阿里云专家博主,华为云享专家,持续输出干货,欢迎关注。

评论

发布
暂无评论
NoClassDefFoundError 和 ClassNotFoundException 有什么区别_NoClassDefFoundError_共饮一杯无_InfoQ写作社区