1. 类的加载、连接与初始化:
(1) 加载:查找并加载类的二进制数据
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构
堆区存放的是对象,方法区存放的是类的基本信息
(2) 连接: 将已经读入内存的类的二进制数据合并到虚拟机的运行时环境中去
- 验证:确保被加载的类的正确性(a. 类文件的结构检查 b. 语法检查 c. 字节码验证 d. 二进制兼容性,确保相互引用的类协调一致)
- 准备:为类的静态变量分配内存,并初始化默认值
- 解析:把类中的符号引用转换为直接引用(例如:在Worker类的gotoWork()方法中会引用Car类的run()方法)
(3) 初始化:为类的静态变量赋予正确的初始值
a. 假如这个类还没有被加载和连接,那就先进行加载和连接
b. 假如类存在直接的父类,并且这个父类还没有被初始化,那就先初始化直接的父类
c. 假如类中存在初始化语句,那就依次执行那些初始化语句
2. java程序对类的主动使用
(1) 创建类的实例 new Test()
(2) 访问某个类或接口的静态变量,或者对该静态变量赋值 int b = Test.a;
(3) 调用类的静态方法 Test.doSomething();
注意:只有当程序访问的静态变量或静态方法确实在当前类或当前接口中定义时,才可以认为是对类或接口的主动使用。
(4) 反射,如Class.forName("com.Test");
(5) 初始化一个类的子类
class Parent{
}
class Child extends Parent{
public static int a = 3;
}
Child.a = 4;
(6) Java虚拟机启动时被表明为启动类的类,如执行 java Test
除了以上六种情况,其他使用Java类的方法都被看做是对类的被动使用,都不会导致类的初始化。
注意:调用ClassLoader类的loadClass方法加载一个类,并不是对类的主动使用,不会导致类的初始化。
3. 加载.class文件的方式
(1) 从本地系统中直接加载
(2) 通过网络下载.class文件
(3) 从jar包中加载.class文件
(4) 从数据库中提取.class文件
(5) 将java源文件编译为.class文件