首页

异常NoClassDefFoundError和ClassNotFoundException区别

标签:NoClassDefFoundError,ClassNotFoundException,类加载,加载顺序,代码执行顺序     发布时间:2016-07-05   

一、前言

JVM将类加载过程分为三个步骤:装载(Load),链接(Link)和初始化(Initialize)链接又分为三个步骤,如语句private static int a = 10 - 先链接所属类,待验证通过后,进入准备阶段,给a分配内存,因为变量a是static的 - 设置a默认初始值0,等到类初始化才将其赋值为10。

异常NoClassDefFoundError和ClassNotFoundException区别

1) 装载:查找并加载类的二进制数据;2)链接:验证 - 确保被加载类的正确性;准备 - 为类的静态变量分配内存,并将其初始化为默认值; 解析 - 把类中的符号引用转换为直接引用;3)初始化:为类的静态变量赋予正确的初始值;

类初始化场景

    1)创建类的实例
    2)访问类或接口的静态变量(static final常量除外,static final变量可以)
    3)调用类的静态方法
    4)反射(Class.forName(packageName.className))
    5)初始化类的子类(子类初始化问题:满足主动调用,即访问子类中的静态变量、方法,否则仅父类初始化)
    6)java虚拟机启动时被标明为启动类的类

备注代码执行顺序:(父类静态成员、静态代码块—>子类静态成员、静态代码块—>父类实例成员、代码块——>父类构造函数—>子类实例成员、代码块—>子类构造函数)

加载类的路径方式

    1)从本地系统直接加载
    2)通过网络下载.class文件
    3)从zip,jar等归档文件中加载.class文件
    4)从专有数据库中提取.class文件
    5)将Java源文件动态编译为.class文件(服务器)

类加载有三种方式:
    1)命令行启动应用时候由JVM初始化加载
    2)通过Class.forName()方法动态加载
    3)通过ClassLoader.loadClass()方法动态加载  

二、区别说明

 如上类加载有三种方式,分别加载不存在类二进制.class文件,会分别抛出NoClassDefFoundError或ClassNotFoundException,具体说明如下

    1)直接创建对象MyObject obj=new MyObject() - 如当前ClassLoader无法找到MyObject类,则抛出NoClassDefFoundError

    2)通过Class.forName()方法动态加载,Class clazz = Class.forName("MyObject");Object obj =clazz.newInstance();通过反射加载类型创建对象实例,如无法找到MyObject类,则抛出ClassNotFoundException

    3)通过ClassLoader.loadClass()方法动态加载,Class clazz = classLoader.loadClass("MyObject");Object dog =clazz.newInstance(); 如无法找到MyObject类,则抛出ClassNotFoundException

注:对于1和2方式都是使用当前执行类加载器进行加载(this.getClass.getClassLoader),3方式是可以让用户自定义的classLoader进行加载