转自:https://blog.csdn.net/dd864140130/article/details/49817357
3. 初始化
和C之类的纯编译型语言不同,Java类文件在编译过程中只会生成class文件,并不会进行连接操作,这意味在编译阶段Java类并不知道引用类的实际地址,因此只能用“符号引用”来代表引用类。举个例子来说明,在com.sbbic.Person类中引用了com.sbbic.Animal类,在编译阶段,Person类并不知道Animal的实际内存地址,因此只能用com.sbbic.Animal来代表Animal真实的内存地址。在解析阶段,JVM可以通过解析该符号引用,来确定com.sbbic.Animal类的真实内存地址(如果该类未被加载过,则先加载)。
主要有以下四种:
类加载过程为:
1. 加载
加载分为三部曲:
- 加载字节码文件,通过限定全类名
- 在方法区中,将静态数据结构转化为动态数据结构,并存在方法区中
- 在堆内存中,生成对应的类对象,作为访问方法区数据的入口
2. 准备
为类变量分配内存(static)在方法区中,并赋值默认值
注意,final修饰的变量在javac执行编译期间就会分配
3. 初始化
关键词,方法<clinit>
定义是:
他是由编译器自动收集初始化行为和执行静态代码块组成
这个方法的特点是:
- 编译器会自动生成的
- 这个方法可能不存在,只要是没有任何需要初始化的变量且没有静态代码块的类
- 父类优先于子类的函数
- 接口可能会有<clinit>函数
- 接口的实现类不会生成<clinit>函数
4. 解析
解析阶段主要任务是将常量池的符号引用转换为直接引用和C之类的纯编译型语言不同,Java类文件在编译过程中只会生成class文件,并不会进行连接操作,这意味在编译阶段Java类并不知道引用类的实际地址,因此只能用“符号引用”来代表引用类。举个例子来说明,在com.sbbic.Person类中引用了com.sbbic.Animal类,在编译阶段,Person类并不知道Animal的实际内存地址,因此只能用com.sbbic.Animal来代表Animal真实的内存地址。在解析阶段,JVM可以通过解析该符号引用,来确定com.sbbic.Animal类的真实内存地址(如果该类未被加载过,则先加载)。
主要有以下四种:
- 类或接口的解析
- 字段解析
- 类方法解析
- 接口方法解析