原文链接:深入理解NoClassDeFoundError与ClassNotFoundException_XiangYida-优快云博客_noclassdefounderror
深入理解NoClassDeFoundError与ClassNotFoundException
1.先看一下两个类
NoClassDeFoundError
ClassNotFoundException
区别在于,一个继承自Exception,另一个继承自Error。
这里就涉及到Exception与Error的区别了。
Exception属于CheckedException错误,就是程序能捕获处理的错误。
而Error属于UnCheckedException,是程序无法捕获处理的错误。
2.NoClassDeFoundError
NoClassDeFoundError继承自LinkageError,根据名字我们就可以猜到这是一个类加载过程中连接时错误。这里涉及到JVM中类加载的过程
类的生命周期图
在Linking的解析阶段:解析阶段是JVM将常量池内的符号引用替换为直接引用的过程
解释一下符号引用与直接引用
符号引用:就是用一组符号来描述所引用的目标,符号引用可以是任何形式的字面量,只要使用时能无歧义的定位到目标即可。
直接引用: 就是直接指向目标的指针
,在类生命周期的解析阶段之前,还只是符号这就是符号引用。 在解析过程中,JVM会去找类是否被加载,如果未加载会先加载类,然后返回类的引用。这就是直接引用
所以,如果在连接阶段的解析时,找不到相应的类,就会报NoClassDeFoundError
假设一个类abc extends ABC
在Windows中,文件名不区分大小写
所以,在编译的时候,先编译父类生成ABC.class然后编译子类abc.class,这个时候由于不区分大小写,abc.class直接覆盖掉了ABC.class的内容了
然后在 解析 阶段的时候,就找不到ABC这个类啦~。所以就报 NoClassDeFoundError 咯~~
(Linux上我已经测试过了,编译后文件内容不会覆盖
3.ClassNotFoundException
这个这个错误其实是经常遇到的。比如JDBC的时候忘了添加驱动。
呐~直接举个例子
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.driver");
}
报错信息
Exception in thread "main" java.lang.ClassNotFoundException: com.mysql.jdbc.driver
···(此处省略)
使用Class.forName();必须要抛出异常或者try/catch。这也是就Excetion与Error的区别。一个是能捕获到的,一个是不能捕获到的错误。
这里的应该是程序运行的时候通过类的全限定名去加载类的时候找不到这个类抛出的异常。
4.最后再总结一下:
NoClassDeFoundError 继承自Error属于用户程序无法捕获处理的异常
ClassNotFoundException 继承自Exception属于用户程序能捕获处理的异常
NoClassDeFoundError 发生在类生命周期中解析阶段找不到相应的类
ClassNotFoundException 发生在类生命周期的加载阶段,找不到相应的类