1

这个一个程序运行中和面试中都经常遇到的问题。
两个错误都是由于系统运行时找不到要加载的类导致,但是他们的触发原因不一样,我们先来看下结论:

异常类型 ClassNotFoundException NoClassDefFoundError
继承模型 从java.lang.Exception继承,是一个Exception类型 从java.lang.Error继承,是一个Error类型
触发原因 当动态加载Class的时候找不到类会抛出该异常 程序在编译时可以找到所依赖的类,但是在运行时找不到指定的类文件,运行过程中Class找不到导致抛出该错误
触发主体 一般在执行Class.forName()、ClassLoader.loadClass()或ClassLoader.findSystemClass()的时候抛出 JVM或者ClassLoader实例尝试加载类的时候,找不到类的定义而发生,通常在importnew一个类的时候触发
处理方式 程序可以从Exception中恢复,ClassNotFoundException可由程序捕获和处理 程序无法从错误中恢复,Error是系统错误,用户无法处理
可能原因 要加载的类不存在;类名书写错误 jar包缺失;调用初始化失败的类

ClassNotFoundException

典型触发场景,调用以下方法时加载失败:

  • Class.forName(),
  • ClassLoader.loadClass()
  • ClassLoader.findSystemClass()
  • 通过反射机制初始化类

如加载数据库驱动时:

public class ExceptionTest {

    public static void main(String[] args)throws Exception {
        Class.forName("oracle.jdbc.driver.OracleDriver");
    }
}

NoClassDefFoundError

典型触发场景如下。
一、编译时存在某个类,但是运行时却找不到

public class A {

    public void hello(){
        System.out.println("hello, world.");
    }
}

 class B {

     public static void main(String[] args) {
         A a = new A();
     }

}

上面的Java类编译后会生成两个类文件,一个A.class,一个B.class,现在我在编译后,删掉了A的class文件,然后直接执行B的main方法,就会抛出NoClassDefFoundError错误,因为当执行到 A a=new A();这一步的时候,JVM认为这个类肯定在当前的classpath里面的,要不然编译都不会通过。既然它存在,那么在JVM里面一定能找到,如果不能找到,那就说明出大事了,因为编译和运行不一致,所以直接抛出这个ERROR,代表问题很严重。

二、一个类没有初始化成功,其他类调用这个类,导致执行失败。
初始化失败的类:

public class  InitFail {

    static double divideZero = 1/0;//故意使得类初始化失败.

    public static void print(){
        System.out.println("123");
    }
}

调用如下:

public static void main(String[] args) {
        try {
            double divideZero = InitFail.divideZero;
        }catch (Throwable e){
        //此处,必须用Throwable,用Exception会直接退出.
            System.out.println(e);
        }
        //继续使用.
        InitFail.print();
    }

这种情况比较特殊,并不是因为编译时和运行时环境不一致导致的,而是对于一个类如果初始化失败后,还继续使用。
JVM会认为是不正常的,由于它第一次调用已经失败,JVM就会假设后面继续调用肯定仍然会失败,所以直接抛ERROR给客户端。

参考:
理解ClassNotFoundException与NoClassDefFoundError的区别


乘着风
107 声望12 粉丝

五岁时,妈妈告诉我,人生的关键在于快乐。上学后,人们问我长大了要做什么,我写下“快乐”。他们告诉我,我理解错了题目,我告诉他们,他们理解错了人生。——约翰·列侬