Java 引用类型
Java 中的引用类型细分为四种: 类, 接口, 数组类和泛型参数.
因为泛型参数会在编译过程中被擦除, 所以 Java 虚拟机实际上只有前三种. 数组类是由 Java 虚拟机直接生成的, 其他两种则有对应的字节流.
无论是数组类还是其他两种类型, Java 虚拟机都需要对其进行链接和初始化.
加载
加载就是查找字节流, 然后据此创建类的过程. 数组类由 Java 虚拟机直接生成, 其他类则需要 Java 虚拟机借助类加载器来完成查找字节流的过程.
类加载器有很多种, 除了启动类加载器以外, 其他的类加载器都是 java.lang.ClassLoader 的子类, 因此有对应的 Java 对象. 这些类加载器都需要先由其他类加载器比如说启动类加载器加载到 Java 虚拟机中, 方能执行类加载.
双亲委派机制: 每当一个类加载器接收到加载请求时, 它会先将请求转发给父类加载器. 如果父类加载器没有找到所请求的类的情况下, 该类加载器才会尝试去加载.
在 Java 9 之前, 启动类加载器负责加载最基础最重要的类. 除了启动类加载器之外, 还有扩展类加载器和应用类加载器, 均由 Java 核心类库提供.
扩展类加载器的父类加载器是启动类加载器. 它负责加载相对次要但通用的类.
应用类加载器的父类加载器是扩展类加载器. 它负责加载应用程序路径下的类.
Java 9 中扩展类加载器被改名为平台类加载器. Java SE 中除了少数几个关键模块是由启动类加载器加载之外, 其他模块均由平台类加载器所加载.
在 Java 虚拟机中, 类的唯一性是由类加载器实例以及类的全名一同确定的.
链接
链接是指将创建成的类合并至 Java 虚拟机中, 使之能够执行的过程. 它可以分为: 验证, 准备和解析三个阶段.
验证阶段: 确保加载类能够满足 Java 虚拟机的约束条件. 通常情况下, Java 编译器生成的类文件必然满足 Java 虚拟机的约束条件.(除了字节码注入)
准备阶段: 为被加载类的静态字段分配内存, 初始化则会在初始化阶段进行. 部分 Java 虚拟机还会在此阶段构造其他跟类层次相关的数据结构, 比如说用来实现虚方法的动态绑定的方法表.
在 class 文件被加载至 Java 虚拟机之前, 这个类无法知道其他类以及其方法和字段所对应的具体地址, 甚至不知道自己方法和字段的地址. 当需要引用这些成员时, Java 编译器会生成一个符号引用, 在运行阶段这些符号引用会定位到具体目标上.
解析阶段就是将这些符号引用解析成为实际引用.
Java 虚拟机规定: 如果某些字节码使用了符号引用, 那么在执行这些字节码之前, 需要完成对这些符号引用的解析. 也就是说, 在链接过程中不要求一定解析完成.
初始化
在 Java 代码中, 初始化一个静态字段, 可以声明时赋值, 也可以在静态代码块中赋值.
如果被赋值的静态字段被 final 修饰, 并且它是基本类型或者字符串时, 那么该字段便会被 Java 编译器标记成常量值, 其初始化直接由 Java 虚拟机完成. 除此之外的直接复制操作每一集静态代码块中的代码, 都会被 Java 编译器置于同一方法中, 命名为
类的初始化, 就是为标记常量的字段赋值, 以及执行
举例一下情况会触发类的初始化:
1: 虚拟机启动时, 初始化用户指定的主类.
2: 遇到 new 指令时, 初始化 new 指令的目标类.
3: 当遇到调用静态方法的指令时, 初始化该静态方法所在的类.
4: 当遇到访问静态字段的指令时, 初始化该静态方法所在的类.
5: 子类的初始化会触发父类的初始化.
6: 如果一个接口定义了 default 方法, 那么实现该接口的类初始化时, 会触发接口的初始化.
7: 使用反射 API 对某个类进行反射调用时, 初始化该类.
问答
Q: 新建类, 和新建类的数组, 初始化过程
新建类的时候, 需要加载, 链接和初始化. 新建类的数组的时候, 由于并没有使用类, 所以只需要加载该类. 如果需要使用该类了, 在执行类的链接和初始化.
Q: 类的初始化和实例的初始化区别, 初始化后的类存储在什么地方
类的初始化只有一次, 通过类的加载链接生成对应的数据结构, 存储在元空间. 实例的初始化可以有多次.
Q: 类中的静态字段, 如果没有被 JVM 标记为常量, 那么如何分配内存
加载类的过程, 都会分配内存, 只是初始化的时候不一样: 一个是在 JVM 中直接复制, 一个是在 clinit 方法中复制.
Q clinit 执行时的锁, 是什么锁, 跟 synchronized 一样吗
clinit 执行时的锁是虚拟机内部锁, 和 synchronized 不一样.
总结
本文创作灵感来源于 极客时间 郑雨迪老师的《深入拆解 Java 虚拟机》课程, 通过课后反思以及借鉴各位学友的发言总结, 现整理出自己的知识架构, 以便日后温故知新, 查漏补缺.
来源: https://www.cnblogs.com/yuepenglei/p/10279996.html