简介
本文介绍Java的类加载流程,有实例。
类加载过程
流程概述
加载=> 链接(验证+准备+解析)=> 初始化=> 使用=> 卸载
- 加载(将硬盘上的Java二进制文件(class文件)转为内存中的Class对象)
- 通过一个类的全限定名获取定义此类的二进制字节流。
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
- 在内存(不一定在堆中,HotSpot是在方法区)中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
- 链接(给静态变量赋初始值,符号引用替换成直接引用)
- 验证:检查载入的class文件数据的正确性
- 准备:给类变量(静态变量)分配内存(方法区)并设置为零值(0、false、null等)。
- 例外:static final类型的String或基本类型,直接赋值为最终值,如:static final int a = 12; 在准备阶段就将a赋值为12。
- 解析(可选):将常量池内的符号引用替换成直接引用。
- 符号引用与虚拟机实现的内存布局无关,引用的目标并不一定已经加载到内存中。直接引用是和虚拟机实现的内存布局相关的,同一个符号引用在不同虚拟机实例上翻译出来的直接引用一般不会相同。如果有了直接引用 ,那引用的目标必定已经在内存中存在。
- 初始化(初始化类变量(静态变量)、执行静态语句块)
- 执行类变量(静态变量)的赋值动作和静态语句块(按定义的顺序从上往下执行)。优先级:静态、父类、子类
- 注意:初始化是操作类变量(也就是静态变量),不是对象的变量。
- 执行类变量(静态变量)的赋值动作和静态语句块(按定义的顺序从上往下执行)。优先级:静态、父类、子类
- 使用(以new一个对象为例)
- 若是第一次创建 Dog 对象(对象所属的类没有加载到内存中)则先执行上面的初始化操作。
- 在堆上为 Dog 对象(包括实例变量)分配空间,所有属性都设成默认值(数字为 0,字符为 null,布尔为 false,引用被设成 null)
- 初始化实例:给实例变量赋值、执行初始化语句块
- 执行构造函数检查是否有父类,如果有父类会先调用父类的构造函数
- 执行本类的构造函数。
对类初始化的场景
虚拟机规范严格规定: 有且只有 5 种情况 必须立即对类进行初始化(加载、验证、准备自然需要在之前执行):
此内容仅限VIP查看,请先登录
请先
!