【JVM】类的声明周期(加载、连接、初始化)


在这里插入图片描述

🐌个人主页: 🐌 叶落闲庭
💨我的专栏:💨
c语言
数据结构
javaEE
操作系统
Redis

石可破也,而不可夺坚;丹可磨也,而不可夺赤。


JVM

  • 一、类的声明周期(加载阶段)
    • 1.1 查看内存中的对象
  • 二、类的声明周期(连接阶段)
    • 2.1 验证
    • 2.2 准备
    • 2.3 解析
  • 三、类的声明周期(初始化阶段)

一、类的声明周期(加载阶段)

  • 1、加载(Loading)阶段第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息程序员可以使用Java代码拓展的不同的渠道。
  • 2、类加载器在加载完类之后,Java虚拟机会将字节码中的信息保存到方法区中。
    • 方法区是一个虚拟概念
  • 3、生成一个InstanceKlass对象,保存类的所有信息,里边还包含实现特定功能比如多态的信息。
    • InstanceKlass包含:基本信息、常量池、字段、方法、虚方法表(实现多态的基础)
  • 4、同时,Java虚拟机还会在堆中生成一份与方法区中数据类似的java.lang.Class)对象。
    • 作用是在ava代码中去获取类的信息以及存储静态字段的数据(JDK8及之后)

在这里插入图片描述


  • 在JDK8开始,静态字段存放在堆区,在JDK8之前是存放在方法区的

方法区中的InstanceKlass对象是用C++编写的,Java代码一般不能直接操作用C++语言编写的对象,所以Java就在堆区上创建了一个Java.lang.Class用Java语言包装之后的对象,可以让Java在代码中获取到,Java.lang.Class对象里包含的字段要少于方法区中InstanceKlass对象包含的字段,这样做的原因是对于开发者来说,并不需要访问InstanceKlass对象中的所有字段信息,例如Java底层实现多态时调用方法区中的虚方法表,这个虚方法表是不需要开发者调用的,这样Java虚拟机就能很好地控制开发者访问数据的范围.。

1.1 查看内存中的对象

  • 使用JDK自带的hsdb工具查看Java虚拟机内存信息,工具位于JDK安装目录下lib文件夹中的sa-jdi.jar中。
  • 启动命令:java -cp sa-jdi.jar sun.jvm.hotspot.HSDB

在这里插入图片描述


在这里插入图片描述


  • 输入java进程号(打开cmd窗口,输入jps命令,就会展示出所有java进程及对应的id)

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


  • 点击Tools->Object Histogram

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


二、类的声明周期(连接阶段)

2.1 验证

  • 验证内容是否满足《Java虚拟机规范》

主要包含如下四部分,具体详见《Java虚拟机规范》:

  • 1.文件格式验证,比如文件是否以OxCAFEBABE开头,主次版本号是否满足当前)ava虚拟机版本要求。

在这里插入图片描述


  • 2.元信息验证,例如类必须有父类(super不能为空)。
  • 3.验证程序执行指令的语义,比如方法内的指令执行中跳转到不正确的位置。
  • 4.符号引用验证,例如是否访问了其他类中privatel的方法等。

Hotspot JDK8中虚拟机源码对版本号检测的代码如下:

return (major >= JAVA_MIN_SUPPORTED_VERSION) &&(major <= max_version)  &&((major != max_version) ||(minor <= JAVA_MAX_SUPPORTED_MINOR_VERSION));
  • major:主版本号
  • minor:副版本号
  • JAVA_MIN_SUPPORTED_VERSION:支持的最低版本,JDK8中常量是45,代表JDK1.0
  • max_version:最高版本,JDK中是52,代表JDK8
  • JAVA_MAX_SUPPORTED_MINOR_VERSION:支持的最高副版本号,JDK未使用,为0
  • 主版本号不能高于运行环境主版本号,如果主版本号相等,副版本号也不能超过。

2.2 准备

  • 给静态变量分配内存并赋初值。
  • 每一种基本数据类型和引用数据类型都有其初始值
数据类型初始值
int0
long0L
short0
char‘\u0000’
byte0
boleanfalse
double0.0
引用数据类型null
  • final修饰的基本数据类型的静态变量,准备阶段直接会将代码中的值进行赋值。

2.3 解析

  • 将常量池中的符号引用替换成指向内存的直接引用
  • 符号引用就是在字节码文件中使用编号来访问常量池中的内容。
  • 直接引用不再使用编号,而是使用内存中地址进行访问具体的数据。

在这里插入图片描述


在这里插入图片描述


三、类的声明周期(初始化阶段)

  • 初始化阶段会执行静态代码块中的代码,并为静态变量赋值
  • 初始化阶段会执行字节码文件中clinit部分的字节码指令,其中cl是class的前两个字母,init就是初始化,所以这一部分的含义就是类的初始化。
  • 源码:
public class Demo4 {public static int value = 1;static {value = 2;}public static void main(String[] args) {}
}
  • 字节码:
iconst_1
putstatic #2 <com/jvmdemo/Demo4.value : I>
iconst_2
putstatic #2 <com/jvmdemo/Demo4.value : I>
return

iconst_1:将常量1放入操作数栈中
putstatic :从操作数栈中获取值设置到静态变量中(即设置value值为1)
iconst_2:将常量2放入操作数栈中
putstatic :从操作数栈中获取值设置到静态变量中(即设置value值为2)

  • clinit方法中的执行顺序与]ava中编写的顺序是一致的。
  • 以下几种方式会导致类的初始化:
      1. 访问一个类的静态变量或者静态方法,(注意:变量是final修饰的并且等号右边是常量不会触发初始化)
      1. 调用Class.forName(String className)
      1. new一个该类的对象时
      1. 执行Main方法的当前类
  • **添加-XX:TraceClassLoading参数可以打印出加载并初始化的类
  • 源码(未添加final修饰):
public class Demo4 {public static void main(String[] args) {int i = Demo5.i;System.out.println(i);}
}
class Demo5 {static {System.out.println("初始化了");}public static int i = 0;
}

在这里插入图片描述

  • 源码(添加final修饰):
public class Demo4 {public static void main(String[] args) {int i = Demo5.i;System.out.println(i);}
}
class Demo5 {static {System.out.println("初始化了");}public static final int i = 0;
}

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/124357.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML5+CSS3+Vue小实例:路飞出海的动画特效

实例:路飞出海的动画特效 技术栈:HTML+CSS+Vue 效果: 源码: 【HTML】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content=&…

第N个斐波那契数列

第N个斐波那契数列 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 class Solution { public:int tribonacci(int n) {int a[4]{0,1,1,2};if(n<4) return a[n];int kn-3;for(int i0; i<k;i){int tmpa[3];a[3]a[1]a[2]a[3];//不是【0】开始&…

Python对象(Object)与类型(Type)的关系

Object与Type 1、Object与Type概述2、Object与Type的关系 1、Object与Type概述 对象&#xff08;Object&#xff09;和类型&#xff08;Type&#xff09;是Python中两个最最基本的概念&#xff0c;它们是构筑Python语言大厦的基石 所有的数据类型&#xff0c;值&#xff0c;变…

代码随想录Day40-单调栈:力扣第496e、503m、42h、84h题

496e. 下一个更大元素 I 题目链接 代码随想录文章讲解链接 方法一&#xff1a;单调栈哈希表 用时&#xff1a;13m52s 思路 维护一个栈底到栈顶是单调递减的栈&#xff0c;从后往前遍历数组nums2&#xff0c;更新栈。nums2当前元素nums2[i]的下一个更大元素就是栈顶元素&am…

【网络安全 --- 文件上传靶场练习】文件上传靶场安装以及1-5关闯关思路及技巧,源码分析

一&#xff0c;前期准备环境和工具 1&#xff0c;vmware 16.0安装 若已安装&#xff0c;请忽略 【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;-CSDN博客文章浏览阅读186次&#xff0c;点赞9次&#xff0c;收藏2次。【网络安全 --- 工…

Kubernetes - Ingress HTTP 升级 HTTPS 配置解决方案(新版本v1.21+)

之前我们讲解过 Kubernetes - Ingress HTTP 搭建解决方案&#xff0c;并分别提供了旧版本和新版本。如果连 HTTP 都没搞明白的可以先去过一下这两篇 Kubernetes - Ingress HTTP 负载搭建部署解决方案_放羊的牧码的博客-CSDN博客Kubernetes - Ingress HTTP 负载搭建部署解决方案…

【Go入门】GO流程与函数介绍(代码运行逻辑控制)

流程和函数 这小节我们要介绍Go里面的流程控制以及函数操作。 流程控制 流程控制在编程语言中是最伟大的发明了&#xff0c;因为有了它&#xff0c;你可以通过很简单的流程描述来表达很复杂的逻辑。Go中流程控制分三大类&#xff1a;条件判断&#xff0c;循环控制和无条件跳…

Mac/Linux类虚拟机_CrossOver虚拟机CrossOver 23.6正式发布2024全新功能解析

CodeWeivers 公司于今年 10 月发布了 CrossOver 23.6 测试版&#xff0c;重点添加了对 DirectX 12 支持&#xff0c;从而在 Mac 上更好地模拟运行 Windows 游戏。 该公司今天发布新闻稿&#xff0c;表示正式发布 CrossOver 23 稳定版&#xff0c;在诸多新增功能中&#xff0c;最…

Mybatis-Plus通用枚举功能 [MyBatis-Plus系列] - 第493篇

历史文章&#xff08;文章累计490&#xff09; 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 S…

GB/T 24718-2023 防眩板检测

防眩板是为解决对向车灯眩光&#xff0c;生产制造的安装在高速公路中央分隔带上的一种交通安全产品&#xff0c;多设置于高速公路中央分隔带护栏上或护栏中间&#xff0c;也有一些设置在中央开口活动护栏上&#xff0c;从材质上分钢制防眩板、塑料防眩板、玻璃钢防眩板。 GB/T…

NOIP2023模拟6联测27 点餐

题目大意 有 n n n样菜品&#xff0c;每样菜品都有两个权值 a i a_i ai​和 b i b_i bi​&#xff0c;如果你选择了 k k k个菜品&#xff0c;分别为 p 1 , … , p k p_1,\dots,p_k p1​,…,pk​&#xff0c;则你的花费为 ∑ i 1 k a p i max ⁡ i 1 k b p i \sum\limits_{i…

3D LUT 滤镜 shader 源码分析

最近在做滤镜相关的渲染学习&#xff0c;目前大部分 LUT 滤镜代码实现都是参考由 GPUImage 提供的 LookupFilter 的逻辑&#xff0c;整个代码实现不多。参考网上的博文也有各种解释&#xff0c;参考了大量博文之后终于理解了&#xff0c;所以自己重新整理了一份&#xff0c;方便…

【无标题】Linux VMware安装centos之后设置静态IP

查看本地IP&#xff1a;ip addr;修改启动协议BOOTPROTOstatic&#xff1b;手动配置IP地址&#xff1b;vi /etc/sysconfig/network-scripts/ifcfg-ens33在最下面增加如下配置 # IP地址 &#xff08;根据自己的环境修改&#xff09; IPADDR192.168.8.101 # 子网掩码 NETMASK255.…

JMeter的使用——傻瓜式学习【中】

目录 前言 1、JMeter参数化 1.1、什么是参数化 1.2、用户定义的变量 1.2.1、什么时候使用用户定义的变量 1.2.2、使用“用户定义的变量”进行参数化的步骤&#xff1a; 1.2.3、案例 1.3、用户参数 1.3.1、什么时候使用用户参数&#xff1f; 1.3.2、使用“用户参数”进…

C现代方法(第15章)笔记——编写大型程序

文章目录 第15章 编写大型程序15.1 源文件15.2 头文件15.2.1 #include指令15.2.2 共享宏定义和类型定义15.2.3 共享函数原型15.2.4 共享变量声明15.2.5 嵌套包含15.2.6 保护头文件15.2.7 头文件中的#error指令 15.3 把程序划分成多个文件15.4 构建多文件程序15.4.1 makefile15.…

10、设置视图组件的Head页面头部标签信息

export default {name: "IndexPage",head() {return {title: "中华小英雄电影第二部",bodyAttrs: {style: "background-color: red;",},meta: [// hid覆盖同名的meta信息{ hid: "description", name: "这是一个关于上学励志教育故…

JSON和Protobuf序列化

文章目录 一、粘包和拆包1、半包问题2、半包现象原理 二、JSON协议通信1、通用类库2、JSON传输的编码器和解码器 三、Protobuf协议通信1、一个简单的proto文件的实践案例2、生成POJO和Builder3、消息POJO和Builder的使用案例1&#xff09;构造POJO消息对象2&#xff09;序列化和…

LeetCode 面试题 16.06. 最小差

文章目录 一、题目二、C# 题解 一、题目 给定两个整数数组 a 和 b&#xff0c;计算具有最小差绝对值的一对数值&#xff08;每个数组中取一个值&#xff09;&#xff0c;并返回该对数值的差 示例&#xff1a; 输入&#xff1a;{1, 3, 15, 11, 2}, {23, 127, 235, 19, 8} 输出&…

基于时间的一次性密码 TOTP 详解

什么是基于时间的一次性密码 TOTP ? 基于时间的一次性密码 TOTP&#xff08;Time-Based One-Time Password&#xff09;&#xff0c;也被称为时间同步动态密码&#xff0c;是一种基于时间的一次性密码算法&#xff0c;通常用于两步验证和多因素身份验证&#xff0c;用于增强静…

【CSDN 每日一练 ★★☆】【二叉树/BSF】二叉树的层序遍历

【CSDN 每日一练 ★★☆】【二叉树/BSF】二叉树的层序遍历 二叉树 BSF 题目 给你一个二叉树&#xff0c;请你返回其按 层序遍历 得到的节点值。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例&#xff1a; 二叉树&#xff1a;[3,9,20,null,nul…