3

NoClassDefFoundError 和 ClassNotFoundException 有什么区别

 1 year ago
source link: https://blog.51cto.com/zhanjq/5959915
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
NoClassDefFoundError 和 ClassNotFoundException 有什么区别_java
NoClassDefFoundError 和 ClassNotFoundException 有什么区别_JVM_02

从类继承层次上来看,ClassNotFoundException是从Exception继承的,所以ClassNotFoundException是一个检查异常。NoClassDefFoundError是从Error继承的。和ClassNotFoundException相比,明显的一个区别是,NoClassDefFoundError并不需要应用程序去关心catch的问题。

NoClassDefFoundError

当JVM在加载一个类的时候,如果这个类在编译时是可用的,但是在运行时找不到这个类的定义的时候,JVM就会抛出一个NoClassDefFoundError错误。比如当我们在new一个类的实例的时候,如果在运行时类找不到,则会抛出一个NoClassDefFoundError的错误。通常发生在执行动态代码块或者初始化静态字段时报了异常,从而导致类初始化失败而引发NoClassDefFoundError。案例如下:

public class ClassWithInitErrors {
    static int data = 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, expected<java.lang.NoClassDefFoundError> but was<java.lang.ExceptionInInitializerError>

	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.<clinit>(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.Driver
	at 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)
ClassNotFoundException NoClassDefFoundError
从java.lang.Exception继承,是一个Exception类型 从java.lang.Error继承,是一个Error类型
当动态加载Class的时候找不到类会抛出该异常 当编译成功以后执行过程中Class找不到导致抛出该错误
一般在执行Class.forName()、ClassLoader.loadClass()或ClassLoader.findSystemClass()的时候抛出 由JVM的运行时系统抛出

他们的主要原因是运行时类路径中类文件不可用。
下面是几点具体的原因:

  1. 排查所需的jar包是否在类路径中,如果没有就添加进去。
  2. 如果发现类在classpath里面,很有可能是classpath被重写了,需要再次确定应用准确的classpath
  3. 依赖包发生了冲突,比如应该依赖高版本jar包,但又其它包传递依赖了低版本jar包,导致高版本中某些类找不到。
  4. 如果应用中用到了多个类加载器,一个类加载器加载的类,无法再其他的类加载器中使用。

本文内容到此结束了,
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位大佬指出。
主页 共饮一杯无的博客汇总👨‍💻

保持热爱,奔赴下一场山海。🏃🏃🏃


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK