简述类加载过程


1. 什么是类加载

类加载就是将class文件加载入内存。
在这里插入图片描述

2. 类加载共五大步骤

  1. 加载
  2. 验证
  3. 准备
  4. 解析
  5. 初始化

五大流程的启动顺序:

注意: 这仅仅是启动过程,也就是说,当加载过程开始,并不一定要等到加载结束才开始下一个过程,而是可以同步进行。
在这里插入图片描述
加载,验证,准备,初始化的先后启动顺序是固定的。

而解析则有两种启动顺序,分别是在准备过程之后,和初始化之后。这样做是为了支持动态绑定

3. 什么时候触发类加载?

什么时候类加载?

见到class文件就加载吗?当然不是。

因此什么时候类加载,回答当然是需要的时候才类加载。

谁需要呢?当然是虚拟机需要的时候。

在考虑完加载动机和需求对象之后,那么我们可以很容易想到:

当因虚拟机需要而触发初始化过程的时候,类加载就已经开始了。

为什么初始化开始就代表类加载开始呢? 与前面说过的启动流程有关。既然启动流程固定顺序是:
加载→验证→准备→…初始化 那么既然触发初始化了,那么其他三个必要过程肯定也相应已经开始。

有且仅有的四种触发初始化方式:

  • 使用new,或者调用类的静态方法等等。 从字节码来说,就是调用了new, getstatic, pustatic, invokestatic这四条字节码指令。
  • 使用反射机制的时候,也就是与Class类有关的时候。
  • 初始化一个类的时候,父类未初始化,就会触发父类的初始化。
  • 包含main方法的类的初始化,会在启动虚拟机时触发。

4. 类加载的具体流程

五个加载过程并不是按照顺序完全独立执行的,而是经常同步执行。

加载过程

加载的目的:

  • 通过类加载器获得二进制字节流。
  • 二进制字节流加载入方法区。
  • 在java堆中创建一个Class对象,作为方法区这个数据结构的访问入口。

验证过程

共有四种验证:

  • 文件格式验证
    开始时间:当在加载过程中获取二进制字节流时。
    目的:验证字节码的结构是否符合虚拟机规范。
    结果:验证成功后字节码被解析到方法区中供后面解析使用。

  • 元数据验证
    开始时间:文件格式验证之后。
    目的:验证字节码的语义,也就是java语言的规范,如是否有父类,是否继承了final修饰的类等等。

  • 字节码验证
    开始时间:紧接着源数据验证之后。
    目的:验证方法体中没有危害虚拟机的行为,但不保证验证过后一定不会出现这种行为。

  • 符号引用验证
    开始时间:解析过程开始之后。
    目的:验证在将符号引用解析为直接引用时,常量池中的符号引用的信息是否正确。

准备过程

准备过程其实很简单,只需要注意与final关键字即可。

准备过程的目的: 仅仅对类变量进行赋值。

  • 如果类变量没有final修饰符,赋值为初始值,如int为0,long为0L,char为’\u0000’ 等等。
  • 如果类变量有final修饰符,如final static int a=123,那么就可以赋值为123.

解析过程

解析过程的目的:根据符号引用验证,将符号引用替换为直接引用。

符号引用的具体时机: 由虚拟机来判断,是在类加载器加载时进行解析,还是等到一个符号引用将要被使用前才进行解析。这也就造成了解析阶段无法确认具体的启动时间的原因。

初始化过程

初始化过程就是执行 <clinit> 方法

<clinit> 是编译器通过收集类中的静态字段,静态代码块自动生成的。

这样的静态字段不会被收集

  • 如果没有赋值,而只是定义,那么不收集。
  • 如果静态字段被final修饰,那么不手机。

不会收集的原因:编译器只会收集有赋值操作的静态字段,而如果被final修饰,那么同时被final,static修饰的字段会放入方法区的常量中,无需赋值操作。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值