刚开始遇到 NoClassDefFoundError 与 ClassNotFoundException 这两种异常的时候,心里好像隐隐约约知道这两者的区别,但是又说不出个所以然,在整理了这两者的区别与联系之后,我想谈谈我对于这两种异常的理解
区别
Error 与 Checked Exception
NoClassDefFoundError 与 ClassNotFoundException 最重要的区别就是,前者是一个 Error,后者是一个 Checked Exception
所谓 Error,Error 意味着错误,在日志等级中 Error 意味着最严重的错误, Error 一般由 JVM 抛出,不像 Exception,程序里一般不对 Error 进行捕获处理,因为当一个程序抛出 Error 的时候基本上就意味着程序恢复不了了,在这种情况下即使能够对 Error 进行捕获那基本上也没有解决方法
而 Checked Exception(即检查型异常)只是一个普通的异常,不过遇到 Checked Exception 的时候,代码需要强制使用 try-catch 进行捕获,否则编译器会报错,而 Error 就不用强制使用 try-catch
抛出的场景不同
假设 class A 在编程的过程当中,引用了 class B ,同时成功对 class A 进行了编译。这时候如果我在 class A 运行之前把 class B 从 classpath 中移除,这时候就会抛出 NoClassDefFoundError ,这个异常在字面上的意思就是 class 的依赖找不到了。我有时候会在使用 Maven 的时候遇到这种异常,说明 pom.xml 中有一个 dependency 还需要另外的一个 dependency
假设 class A 在编程的过程当中,使用 Class.forName()、ClassLoader.loadClass() 或者 ClassLoader.findSystemClass() 等的方法动态加载 class,但是所加载的 class 不存在的时候,这时候抛出的就是 ClassNotFoundException
NoClassDefFoundError 本质上还是 ClassNotFoundException
下图是 NoClassDefFoundError 的堆栈信息:
可以发现:NoClassDefFoundError 的 caused exception 为 ClassNotFoundException ,说明在抛出 NoClassDefFoundError 之前,还抛出了一个 ClassNotFoundException ,这表明 runtime system 在程序启动的过程中先捕获到了一个 ClassNotFoundException ,然后在处理这个 ClassNotFoundException 的时候又重新抛出了 NoClassDefFoundError 异常。
所以说,我个人的理解就是 NoClassDefFoundError 本质上其实还是 ClassNotFoundException ,只不过 NoClassDefFoundError 代表抛出 ClassNotFoundException 的场景不同, 因为这时候的 ClassNotFoundException 并不是程序在动态加载过程中抛出的,而是在程序启动过程中抛出的