生命周期
类从被加载到虚拟机内存中开始,到卸载出内存为止,是它的整个生命周期,其中包含
- 加载 Loading
- 链接 Linking(验证 Verification,筹备 Preparation,解析 Resolution)
- 初始化 Initialization
- 应用 Using
- 卸载 Unloading 7 个阶段
阶段程序
加载、校验、筹备、初始化、卸载 这五个阶段的程序是确定的,然而【解析】则不肯定,在某些状况下能够在初始化之后才开始,这样做是为了反对 java 的运行时绑定特色(也称为前期绑定)
何时加载
- 启动 main 办法时
- 创立类的实例
- 创立子类的实例
- 拜访类的静态方法
- 反射 Class.forName()
加载机会知识点
加载
通过类的全限定名获取该类的二进制字节流;
将二进制字节流所代表的动态构造转化为办法区的运行时数据结构;
在内存中创立一个代表该类的 java.lang.Class 对象,作为办法区这个类的各种数据的拜访入口
链接
验证
验证阶段确保 Class 文件的字节流中蕴含的信息合乎以后虚拟机的要求,并且不会危害虚拟机本身的平安,包含
- 文件格式验证;验证字节流是否合乎 Class 文件格式的标准,并且能被以后版本的虚拟机解决
- 是否以魔数 “0XCAFEBABE” 结尾;
- 主次版本号是否在以后虚拟机解决范畴内;
- 常量池是否有不被反对的常量类型;
- 指向常量的索引值是否指向了不存在的常量;
- CONSTANT_Utf8_info 型的常量是否有不合乎 UTF8 编码的数据
- 元数据验证;对字节码形容信息进行语义剖析,确保其合乎 Java 语法标准
- 字节码验证;本阶段是验证过程中最简单的一个阶段,是对办法体进行语义剖析,保障办法在运行时不会呈现危害虚拟机的事件
- 符号援用验证;本阶段产生在解析阶段,确保解析失常执行
筹备
筹备阶段是正式为类变量(或称 动态成员变量)分配内存并设置初始值的阶段。这些变量(不包含实例变量)所应用的内存都在办法区中进行调配。初始值通常状况下是数据类型的零值(0, null),假如一个类变量的定义为:
public static int value = 123;
变量 value 在筹备阶段过后的初始值为 0 而不是 123,因为这时候尚未开始执行任何 Java 办法。如果类字段的字段属性表中存在 ConstantValue 属性,那么在筹备阶段 value 就会被初始化为 ConstantValue 属性所指定的值,假如下面类变量 value 的定义变为:
public static final int value = 123;
那么在筹备阶段虚构机会依据 ConstantValue 的设置将 value 赋值为 123。
解析
解析阶段是虚拟机将常量池内的符号援用替换为间接援用的过程。
符号解析知识点
初始化
类初始化阶段是类加载过程的最初一步,是执行类结构器 <clinit>() 办法的过程。<clinit>() 办法是由编译器主动收集类中的所有类变量的赋值动作和动态语句块(static {} 块)中的语句合并产生的,编译器收集的程序是由语句在源文件中呈现的程序所决定的。动态语句块中只能拜访定义在动态语句块之前的变量,定义在它之后的变量,在后面的动态语句块中能够赋值,但不能拜访
public class Fentity {
{System.out.println("this is father");
}
public Fentity() {System.out.println("father is created");}
public void test(){System.out.println("father test");}
}
public class Centity extends Fentity {
{System.out.println("this is child");
}
public Centity() {System.out.println("child is created");}
public void test() {System.out.println("child test");}
}
public static void main(String[] args) {Fentity c = new Centity();
c.test();}
输入后果
father is created
this is child
child is created
child test
参考资料:
https://blog.csdn.net/weixin_…
https://blog.csdn.net/chenshm…
https://blog.csdn.net/xing_ji…