jvms规定了下面几种情况下将会抛出NoClassDefFoundError和ClassNotFoundException。
1:
If the Java Virtual Machine ever attempts to load a class C during verification
(§5.4.1) or resolution (§5.4.3) (but not initialization (§5.5)), and the class loader
that is used to initiate loading of C throws an instance of ClassNotFoundException,
then the Java Virtual Machine must throw an instance of NoClassDefFoundError
whose cause is the instance of ClassNotFoundException.
(A subtlety here is that recursive class loading to load superclasses is performed
as part of resolution (§5.3.5, step 3). Therefore, a ClassNotFoundException that
results from a class loader failing to load a superclass must be wrapped in a
NoClassDefFoundError.)
这里需要说明的一点是,类加载过程中,虚拟机会调用java.lang.ClassLoader.loadClass这个java方法(注意是虚拟机调用java方法)。loadClass 方法找不到class文件时会抛出ClassNotFoundException。然后虚拟机捕获这个异常,封装成NoClassDefFoundError。还有一点需要提到的是,类加载一旦失败,对于这个类永远处于失败状态。比如说因为class文件不小心被删除了,classLoader加载时(classloader采用了延迟加载的机制)找不到class文件导致了加载失败,我们重新把对应的class文件放到classpath下面,仍然会出现NoClassDefFoundError,注意ClassNotFoundException不会出现了。原因参考下面第二点。
2:
If the Class object for C is in an erroneous state, then initialization is not
possible. Release LC and throw a NoClassDefFoundError.
jvms定义了在初始化阶段Class对象有4种状态,如果处于erroneous状态的话虚拟机也会抛出NoClassDefFoundError。
It assumes that the Class object
has already been verified and prepared, and that the Class object contains state
that indicates one of four situations:
• This Class object is verified and prepared but not initialized.
• This Class object is being initialized by some particular thread.
• This Class object is fully initialized and ready for use.
• This Class object is in an erroneous state, perhaps because initialization was
attempted and failed
总结:ClassNotFoundException是有ClassLoader抛出来的,NoClassDefFoundError是由JVM抛出来的。
来一个实例吧