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