Java中NoClassDefFoundError|Java中NoClassDefFoundError 和 ClassNotFoundException的区别
目录
- NoClassDefFoundError
- ClassNotFoundException
- 解决办法
文章图片
从类继承层次上来看,ClassNotFoundException是从Exception继承的,所以ClassNotFoundException是一个检查异常。NoClassDefFoundError是从Error继承的。和ClassNotFoundException相比,明显的一个区别是,NoClassDefFoundError并不需要应用程序去关心catch的问题。
NoClassDefFoundError 当JVM在加载一个类的时候,如果这个类在编译时是可用的,但是在运行时找不到这个类的定义的时候,JVM就会抛出一个NoClassDefFoundError错误。比如当我们在new一个类的实例的时候,如果在运行时类找不到,则会抛出一个NoClassDefFoundError的错误。通常发生在执行动态代码块或者初始化静态字段时报了异常,从而导致类初始化失败而引发NoClassDefFoundError。
案例如下:
public class ClassWithInitErrors {static int data = https://www.it610.com/article/1 / 0; }public class NoClassDefFoundErrorTest {public ClassWithInitErrors getClassWithInitErrors() {ClassWithInitErrors test = new ClassWithInitErrors(); return test; }@Test(expected = NoClassDefFoundError.class)public void givenInitErrorInClass_whenloadClass_thenNoClassDefFoundError() {NoClassDefFoundErrorTest sample= new NoClassDefFoundErrorTest(); sample.getClassWithInitErrors(); }}
执行程序后会出现如下错误:
java.lang.Exception: Unexpected exception, expectedbut was
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
...more
Caused by: java.lang.ArithmeticException: / by zero
at com.zjq.dailyrecord.throwable.ClassWithInitErrors.(ClassWithInitErrors.java:4)
... 25 more
ClassNotFoundException 当应用程序运行的过程中尝试使用类加载器去加载Class文件的时候,如果没有在classpath中查找到指定的类,就会抛出ClassNotFoundException。一般情况下,当我们使用Class.forName()或者ClassLoader.loadClass以及使用ClassLoader.findSystemClass()在运行时加载类的时候,如果类没有被找到,那么就会导致JVM抛出ClassNotFoundException。
最简单的,当我们使用JDBC去连接数据库的时候,我们一般会使用Class.forName()的方式去加载JDBC的驱动,如果我们没有将驱动放到应用的classpath下,那么会导致运行时找不到类,所以运行Class.forName()会抛出ClassNotFoundException。
案例如下:
public class ClassNotFoundExceptionTest {public static void main(String[] args) {try {Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) {e.printStackTrace(); }}}
执行后输出:
java.lang.ClassNotFoundException: com.mysql.jdbc.Driverat java.net.URLClassLoader.findClass(URLClassLoader.java:381)at java.lang.ClassLoader.loadClass(ClassLoader.java:424)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)at java.lang.ClassLoader.loadClass(ClassLoader.java:357)at java.lang.Class.forName0(Native Method)at java.lang.Class.forName(Class.java:264)at com.zjq.dailyrecord.throwable.ClassNotFoundExceptionTest.main(ClassNotFoundExceptionTest.java:6)总结区别:
文章图片
解决办法 他们的主要原因是运行时类路径中类文件不可用。
下面是几点具体的原因:
- 排查所需的jar包是否在类路径中,如果没有就添加进去。
- 如果发现类在classpath里面,很有可能是classpath被重写了,需要再次确定应用准确的classpath
- 依赖包发生了冲突,比如应该依赖高版本jar包,但又其它包传递依赖了低版本jar包,导致高版本中某些类找不到。
- 如果应用中用到了多个类加载器,一个类加载器加载的类,无法再其他的类加载器中使用。
推荐阅读
- 详解SpringBoot如何删除引用jar包中的无用bean
- 投稿|上市半个月市值3100亿美元,超阿里中石油,尚乘数科是什么公司?
- CSS布局随手记
- 中智德智慧路灯5G智慧路灯杆市场预算
- APISpace 中文简繁转换API
- JAVA快速排序代码
- 投稿|深度剖析预制菜演化史:在变局中找发展
- 聚焦大公司动态|GDR上市提速,中企海外融资迎来小高潮
- java|springboot 整合redis集群
- 投稿|在线招聘江湖:老、中、新三代平台对垒