【JVM】——类的生命周期——连接阶段和初始化阶段

【喜欢的话可以一键三连+关注哦~】 你的三连+关注是对我最大的支持!之后也会继续更新本专栏呦 ~~
连接阶段
验证

验证内容是否满足《Java虚拟机规范》(这个阶段程序员一般不需要参与)

准备

给静态变量(static)分配内存设置初始值

final修饰的基本数据类型的静态变量,准备阶段直接会将代码中的值进行赋值。

解析

将常量池中的符号引用替换成指向内存的直接引用

符号引用就是在字节码文件中使用编号来访问常量池中的内容

直接引用不在使用编号,而是使用内存中地址进行访问具体的数据

初始化阶段

这个value的值为1是从初始化阶段来完成的。

初始化阶段会执行静态代码块中的代码,并为静态变量赋值

初始化阶段会执行字节码文件中clinit(类的初始化)部分的字节码指令。

具体流程:

首先执行源码里面的那个语句(如图片),然后执行字节码指令将常量1放入操作数栈。

将操作数栈中的1赋值给常量池中编号为2的变量,它就是Demo1里面的value变量。由于在之前在堆区中给value赋值为0,这时我们需要将操作数栈中的1赋值进去。

之后的步骤就与上面的流程类似(图片在下)

那么问题来了,如果说将上面两句话对调顺序,结果会怎么样呢?

由于clinit方法中的执行顺序与Java中编写的顺序是一致的,所以最终的结果是1

以下几种方式会导致类的初始化:

1.访问一个类的静态变量或者静态方法,注意变量是final修饰的并且等号右边是常量不会触发初始化。

2.调用Class.forName(String className)。

3.new一个该类的对象时。

4.执行Main方法的当前类。

这个参数的开启方式

最后在点击一下OK,我们就开启成功了!!!!

大厂面试题!!!!!!

执行main方法先初始化Test1的初始化方法,输出结果为DA。

执行两次Test1的构造方法,输出结果为DACBCB

插一嘴:是不是有人会有疑惑?为什么C会在B前面执行?其原因是{}是构造代码块,每一次创建对象时执行,始终在构造方法前执行。

整体的执行步骤:

clinit指令在特定情况下不会出现,比如:如下几种情况是不会进行初始化指令执行的。

1.无静态代码块且无静态变量赋值语句。

2.有静态变量的声明,但是没有赋值语句。

3.静态变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化。

出现继承初始化阶段会怎么样呢?

直接访问父类的静态变量,不会触发子类的初始化。

子类的初始化clinit调用之前,会先调用父类的clinit初始化方法。

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值