平时工作中,程序启动时有时报找不到类的异常,这个问题的唯一原因就是classpath下没有这个类的class文件。
现在JAVA项目大多使用Maven进行包管理,很多时候项目本身直接依赖的包和第三方的间接依赖的包是不同的版本,比如说项目直接依赖的是低版本,某一个第三方包间接依赖的是比较高版本的,需要使用到其中新增加了一些新的类。如果没有明确指定包的版本的话,就会根据Maven的默认规则决定使用哪个版本的包。这就可能导致最终使用的是一个不合适的版本,导致程序在运行期间会抛出NoClassDefFoundError或者ClassNotFoundException(为什么能编译通过? 因为你自己的代码并没有直接引用这个类,编译的时候不会有任何问题)
同样是找不到类,为什么有时候异常是NoClassDefFoundError,而有时候是ClassNotFoundException呢。首先Error和Exception是两种不同级别的异常,看下JAVA文档里对Error和Exception的定义:
Error
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.
Exception
The class Exception and its subclasses are a form of Throwable that indicates conditions that a reasonable application might want to catch.
NoClassDefFoundError一般是JVM通过默认的Classloader在进行类加载、链接的时候,找不对对应的Class文件而抛出来的,它的cause也是ClassNotFoundException。
ClassNotFoundException一般不会是直接抛出来的最上层的异常。现在很多项目都会使用第三方的框架或者运行在容器中,这些框架通常都会定义自己的Classloader去加载不同的类,然后通过反射去操作这些类。当找不对对应的Class文件时,自定义的Classloader也会抛出ClassNotFoundException,框架可以捕获这个异常,并将其包装成具体的异常,然后向上抛出。
总结
1.ClassNotFoundException是在类加载时找不到class文件时抛出的异常
2.JVM默认的Classloader在遇到ClassNotFoundException时,会抛出NoClassDefFoundError
3.自定义Classloader进行管理类加载的框架或容器,在遇到ClassNotFoundException时,通常会抛出和当前具体错误相关的异常