ClassNotFoundException与NoClassDefFoundError的区别是java面试的常见题目之一,这种题目怎么可以答错呢?
Java开发中常见两种查找不到Class的异常,分别是
java.lang.ClassNotFoundException和java.lang.NoClassDefFoundError,二者主要区别是显式装载的时候找不到类还是隐式装载的时候找不到类。 在Java中,类需要被类加载器加到到JVM内存中才能被使用,类的装载有两种方式
一、显式装载
程序中使用指定的方法加载指定的类,目前有以下三种情况
- Class.forName()
- ClassLoader的loadClass方法
- ClassLoader的findSystemClass()方法(protected final,只能在本类或者继承的子类才可以使用)
当调用以上任何一个方法的时候,指定的类由类装入器装入。如果类已经装入,那么只是返回一个引用;否则,装入器会通过委托模型装入类。
二、隐式装载
隐式 类装入发生在由于引用、实例化(new)或继承导致装入类的时候(不是通过显式方法调用)。在每种情况下,装入都是在幕后启动的,JVM 会解析必要的引用并装入类。与显式类装入一样,如果类已经装入了,那么只是返回一个引用;否则,装入器会通过委托模型装入类。 类的装入通常组合了显式和隐式类装入。例如,类装入器可能先显式地装入一个类,然后再隐式地装入它引用的所有类。
ClassNotFoundException发生在显式装载类的时候查找不到对应的类文件的时候;
NoClassDefFoundError发生在隐式装载类的时候查找不到对应的类文件的时候,此时执行的类已经编译但是在执行的时候找不到定义的类文件,存在searched-for类定义,也就是说引用的类在类路径中没有找到。例如存在一个Maven多模块工程,在其中一个war Maven模块中通过new或者引用隐式引入了某个类,此时编译总是成功的,然而有另外一个Maven模块是用来将工程打包成ear包部署到WAS中的,此时此模块打包的时候漏掉了在war Maven模块中引用的类所在的包,此时打包成功,但是执行的时候就会出现 NoClassDefFoundError。