JVM详解之类加载

一、类的加载过程(生命周期)

1. 说说类加载分为几步

1-1都谁需要加载?

在Java中数据类型分为基本数据类型和引用数据类型。

基本数据类型由虚拟机预先定义,引用数据类型则需要进行类加载

1-2.类加载的步骤

装载

链接:

​ 验证

​ 准备

​ 解析

初始化

类的使用

类的销毁

2. 类加载流程图

3. Loading(装载)阶段

3-1 装载阶段做了什么

所谓装载,就是将Java类的字节码文件加载到机器内存中,并在内存中构建出Java类的原型----类模板对象
装载阶段,就是查找并加载类的二进制数据,生成Class的实例

3-2 类模板对象

类模板对象,就好比Java类的"设计图纸",JVM将其都存在"方法区"中,有了类模板对象,才能在程序运行时通过反射机制来了解和操作这个了类
JDK1.8 之前,存在方法区 但 JDK1.8 之后,存在元空间

3-3 二进制流的获取方式

3-4 Class实例的存储位置

将.clas文件加载至元空间后,会在堆中创建一个Java.long.Class对象,用来封装类位于方法区内的数据结构
该Class对象是在加载类的过程创建的,每个类都应有一个Class类型的对象。

3-5 数组类的加载

数组类本身并不是由类加载器负责创建的,而是由JVM在运行时根据需要而直接创建的,但数组的元素类型仍需要依靠类加载器去创建。
创建数组类的过程:

如果数组元素类型是引用类型,那就遵循定义的加载过程递归加载和创建数组的元素类型

JVM使用指定的元素类型和数组维度来创建新的数组类

如果数组的元素类型是引用数据类型,数组类的可访问性就由元素类型的可访问性决定。

4. Linking(链接)阶段

4-1 验证

验证是链接操作的第一步,它的目的是保证加载的字节码是合法,合理并符合规范的

4-2 准备

准备阶段就是为类的静态变量分配内存,并将其初始化为默认值。
注意:

不包含基本数据类型的字段用static final 修饰的情况,因为final在编译的时候就会分配了,准备阶段会显式赋值

5. 解析

简而言之,将类,接口,字段和方法的符号引用转为直接引用

5 Initialization(初始化)阶段

5-1 子类加载前先加载父类

在加载类之前,虚拟机会先加载该类的父类。
因此父类的<clinit>总是在子类的<clinit>之前被调用。因此父类的static块优先级高于子类

5-2 那些类不会生成<clinit>方法

5.2.1 类中没有声明任何类变量,也没有静态代码块
5.2.2 类中声明类变量,但没使用类变量的初始化语句以及静态代码块来执行初始化操作
5.2.3 类中包含static final修饰的基本数据类型的字段

/**

* 哪些场景下,java编译器就不会生成<clinit>()方法

*/

public class InitializationTest1 {

//场景1:对于非静态的字段,不管是否进行了显式赋值,都不会生成<clinit>()方法

public int num = 1;

//场景2:静态的字段,没有显式的赋值,不会生成<clinit>()方法

public static int num1;

//场景3:比如对于声明为static final的基本数据类型的字段,不管是否进行了显式赋值,都不会生成<clinit>()方法

public static final int num2 = 1;

}

5-3 static与final的搭配问题

5-4 <clinit>()的调用会死锁吗

虚拟机为了保证<clinit>()方法只执行一次,会为这个方法上一把锁。这意味着,即使多个线程同时初始化同一个类,也只有一个线程能进去执行,其他线程必须在外面排队等待。这种机制保证了线程安全,但如果初始化方法本身耗时过长,就会导致所有等待的线程都被阻塞,引发一种难以排查的死锁问题。不过一旦类初始化完成后,后续需要使用这个类的线程就可以直接享受成果,无需再等待。

5-5 类的初始化情况:主动使用 vs 被动使用

主动使用:new一个新对象、调用静态方法、访问静态变量、强制要求加载类、子类调用父类成员、接口定义默认方法、类包含main方法
被动使用:被动使用即不进行初始化操作
全部评论

相关推荐

timeline:一面&nbsp;9/10自我介绍实习挖掘项目挖掘:Embedding时用到的向量数据库,文章解析和分块的功能等,ES的原理,召回的策略实习比较大的挑战和难点是什么项目关于Redis有用到哪些情景Redis是内存数据库,有什么机制去防止数据丢失(RDB,AOF)Redis如何处理过期的情况Redis有哪些具体的数据结构介绍一下BitMap介绍一下ZSet提到了ZSet用于排行榜,如果相同分数但是我想让先达到这个分数的人排在前面,如何设计(加时间戳的综合score)ZSet的底层实现是什么样的,讲解一下数据库中有比较大的表,如何进行分表,比较的依据有哪些数据库事务的特性ACID介绍一下索引,索引和事务的关联手撕:lc485,最大连续1的个数二面&nbsp;9/19自我介绍问实习项目用kafka用在了哪里为什么选用kafka,不用其他的消息队列为什么文件上传这种轻量的要用kafka消息队列的丢失如何处理如何监控是否上传成功告警的频率以及如何设置的,是埋点还是别的是实时的数据吗还是离线的数据同步看板是利用了什么方式如果看板数据无穷无尽的话grafana搞不定怎么解决kafka发送一条消息到消费经历什么过程如果超过最大处理次数都没有成功会怎样手撕:lc109:有序链表转换二叉搜索树三面10/9自我介绍问实习提示词优化了什么,技术难点校验规则变化了怎么处理XXL-Job讲一下怎么用的XXL-Job的推和拉,有什么区别哪个好手撕:lc581:最短无序连续子数组hr面&nbsp;10/14意向&nbsp;10/21感谢字节收留
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务