当前位置: 首页 > news >正文

JVM——类的生命周期(加载阶段,连接阶段,初始化阶段)

目录

  • 1.加载阶段
  • 2.连接阶段
    • 1.验证
    • 2.准备
    • 3.解析
  • 3.初始化阶段
  • 4.总结

在这里插入图片描述
类的生命周期
在这里插入图片描述

1.加载阶段

⚫ 1、加载(Loading)阶段第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息。
程序员可以使用Java代码拓展的不同的渠道。
⚫ 2、类加载器在加载完类之后,Java虚拟机会将字节码中的信息保存到方法区中。
⚫ 3、类加载器在加载完类之后,Java虚拟机会将字节码中的信息保存到内存的方法区中。
生成一个InstanceKlass对象,保存类的所有信息,里边还包含实现特定功能比如多态的信息。
在这里插入图片描述
⚫ 4、同时,Java虚拟机还会在堆中生成一份与方法区中数据类似的java.lang.Class对象。
作用是在Java代码中去获取类的信息以及存储静态字段的数据(JDK8及之后存放在堆区中)。在JDK8以前是静态字段存放在方法区中
主要作用:在实现反射的时候需要先拿到类的基本的信息(class对象)通过其获取其内的方法和字段,进行一系列的操作。
在这里插入图片描述
⚫ 对于开发者来说,只需要访问堆中的Class对象而不需要访问方法区中所有信息。
这样Java虚拟机就能很好地控制开发者访问数据的范围。

  1. instanceKlass是使用C++语言编写的对象,Java语言不能直接去操作这个对象,
  2. Java.lang.Class类中包含的字段要少于instanceKlass中的,instanceKlass中的许多字段是开发者用不到的,为了保护这些数据,Java.lang.Class类中只包含开发者需要用到的方法等字段。

在这里插入图片描述

2.连接阶段

在这里插入图片描述

1.验证

⚫ 连接(Linking)阶段的第一个环节是验证,验证的主要目的是检测Java字节码文件是否遵守了《Java虚拟机规
范》中的约束。这个阶段一般不需要程序员参与。
⚫ 主要包含如下四部分,具体详见《Java虚拟机规范》:

  1. 文件格式验证,比如文件是否以0xCAFEBABE开头,主次版本号是否满足当前Java虚拟机版本要求。
  2. 元信息验证,例如类必须有父类(super不能为空)。
  3. 验证程序执行指令的语义,比如方法内的指令执行到一半强行跳转到其他方法中去。
  4. 符号引用验证,例如是否访问了其他类中private的方法等

2.准备

⚫ 准备阶段为静态变量(static)分配内存并设置初始值。
⚫ 注意:涉及到的内存结构只讨论JDK8及之后的版本
在这里插入图片描述

⚫ 准备阶段只会给静态变量赋初始值,而每一种基本数据类型和引用数据类型都有其初始值。
注: final修饰的基本数据类型的静态变量,准备阶段直接会将代码中的值进行赋值在这里插入图片描述

3.解析

⚫ 解析阶段主要是将常量池中的符号引用替换为直接引用。
⚫ 符号引用就是在字节码文件中使用编号来访问常量池中的内容在这里插入图片描述
⚫ 直接引用不在使用编号,而是使用内存中地址进行访问具体的数据。在这里插入图片描述

3.初始化阶段

⚫ 初始化阶段会执行静态代码块中的代码,并为静态变量赋值。
⚫ 初始化阶段会执行字节码文件中clinit部分的字节码指令。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
⚫ 以下几种方式会导致类的初始化:
1.访问一个类的静态变量或者静态方法,注意变量是final修饰的并且等号右边是常量不会触发初始化。
2.调用Class.forName(String className)。
3.new一个该类的对象时。
4.执行Main方法的当前类。
在这里插入图片描述
在这里插入图片描述
⚫ clinit指令在特定情况下不会出现,比如:如下几种情况是不会进行初始化指令执行的。
1.无静态代码块且无静态变量赋值语句。
2.有静态变量的声明,但是没有赋值语句。
3.静态变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化。在这里插入图片描述
⚫ 直接访问父类的静态变量,不会触发子类的初始化。
⚫ 子类的初始化clinit调用之前,会先调用父类的clinit初始化方法。
在这里插入图片描述
在这里插入图片描述
数组的创建不会导致数组中元素的类进行初始化。
在这里插入图片描述
final修饰的变量如果赋值的内容需要执行指令才能得出结果,会执行clinit方法进行初始化。
在这里插入图片描述

4.总结

在这里插入图片描述
在这里插入图片描述
几个要点:
1.静态变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化
(除非要执行方法)。
2.直接访问父类的静态变量,不会触发子类的初始化。子类的初始化cinit调用之前,
会先调用父类的cinit初始化方法。
在这里插入图片描述

http://www.lryc.cn/news/215103.html

相关文章:

  • CSS中实现元素居中的几种方法总结
  • 保护听力戴什么耳机比较好?开放式耳机能保护听力吗?
  • 【JVM】垃圾回收机制
  • MySQL数据库入门到精通——运维篇(2)
  • 投资者如何保障个人利益?行业律师与欧科云链专家给出建议
  • 【办公软件】C#调用NPOI实现Excel文件的加载、导出功能
  • UVA 11990 “Dynamic‘‘ Inversion 区域树 + 树状数组
  • 邮件钓鱼分析
  • Android 小技巧
  • Centos MySQL --skip-grant-tables详解
  • Linux:进程控制的概念和理解
  • ubuntu20.04编译安装nginx
  • 操作系统的分页
  • 微服务环境搭建
  • ffmpeg 截取命令
  • TypeScript深度剖析:TypeScript 中枚举类型应用场景?
  • [推荐]SpringBoot,邮件发送附件含Excel文件(含源码)。
  • node学习之包管理器
  • 自动驾驶车辆轨迹跟踪
  • React的useEvent 和 ahooks 的 useMemorizedFn 的深度分析和对比
  • 基于goframe2.5.4、vue3、tdesign-vue-next开发的全栈前后端分离的管理系统
  • LInux之在同一Tomcat下使用不同的端口号访问不同的项目
  • 梦百合上榜2023鼎革奖数字化转型先锋榜
  • 沉痛悼念科研分公司
  • Django的网站项目开发好了,该用何种方案在Centos上部署【答:Gunicorn(uWSGI)+Nginx】
  • 基于PyTorch的中文情绪分析器设计与开发
  • HT5010 音频转换器工作原理
  • ubuntu18.04如何更新到22.04
  • 嵌入式软件开发:第二部分–七个步骤计划
  • 什么是IPA,和RPA有啥区别和联系?