【JVM从入门到实战】(四)类的生命周期
什么是类的生命周期
类的生命周期描述了一个类加载、连接、初始化、使用、卸载的整个过程
一个类完整的生命周期如下:

加载阶段
-
加载阶段第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息。
程序员可以使用Java代码拓展的不同的渠道。加载渠道:本地磁盘的字节码文件、程序运行时使用动态代理生成的文件、通过网络传输的类比如早期的Applet技术使用
-
类加载器在加载完类之后,Java虚拟机会将字节码中的信息保存到方法区中。
-
类加载器在加载完类之后,Java虚拟机会将字节码中的信息保存到内存的方法区中。生成一个
InstanceKlass对象,保存类的所有信息,里边还包含实现特定功能比如多态的信息。

4、同时,Java虚拟机还会在堆中生成一份与方法区中数据类似的java.lang.Class对象。
作用是在Java代码中去获取类的信息以及存储静态字段的数据(JDK8及之后)。

对于开发者来说,只需要访问堆中的Class对象而不需要访问方法区中所有信息。这样Java虚拟机就能很好地控制开发者访问数据的范围。
加载阶段 – 查看内存中的对象
推荐使用 JDK自带的hsdb工具查看Java虚拟机内存信息。工具位于JDK安装目录下lib文件夹中的sa-jdi.jar中。
启动命令:java -cp sa-jdi.jar sun.jvm.hotspot.HSDB
连接阶段
连接(Linking)阶段的第一个环节是验证,验证的主要目的是检测Java字节码文件是否遵守了《Java虚拟机规范》中的约束。这个阶段一般不需要程序员参与。
主要包含如下四部分,具体详见《Java虚拟机规范》:
1.文件格式验证,比如文件是否以0xCAFEBABE开头,主次版本号是否满足当前Java虚拟机版本要求

2.元信息验证,例如类必须有父类(super不能为空)。
3.验证程序执行指令的语义,比如方法内的指令执行中跳转到不正确的位置。
4.符号引用验证,例如是否访问了其他类中private的方法等。
连接阶段的第二个环节是准备,准备阶段为静态变量(static)分配内存并设置初始值。
(这里涉及到的内存结构只讨论JDK8及之后的版本)

准备阶段只会给静态变量赋初始值,每一种基本数据类型和引用数据类型都有其初始值。
final修饰的基本数据类型的静态变量,准备阶段直接会将代码中的值进行赋值。

连接阶段的第三个环节是解析,解析阶段主要是将常量池中的符号引用替换为直接引用。符号引用就是在字节码文件中使用编号来访问常量池中的内容

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

初始化阶段
初始化阶段会执行静态代码块中的代码,并为静态变量赋值。
初始化阶段会执行字节码文件中clinit部分的字节码指令。

以下几种方式会导致类的初始化:
- 访问一个类的静态变量或者静态方法,注意变量是final修饰的并且等号右边是常量不会触发初始化。
- 调用Class.forName(String className)。
- new一个该类的对象时。
- 执行Main方法的当前类
添加-XX:+TraceClassLoading 参数可以打印出加载并初始化的类
一道面试题:
写出下面左边程序的打印结果


结果:输出结果DACBCB
clinit指令在特定情况下不会出现,比如:如下几种情况是不会进行初始化指令执行的。
- 无静态代码块且无静态变量赋值语句。
- 有静态变量的声明,但是没有赋值语句。
- 静态变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化。
注意:
- 直接访问父类的静态变量,不会触发子类的初始化。
- 子类的初始化clinit调用之前,会先调用父类的clinit初始化方法。


- 数组的创建不会导致数组中元素的类进行初始化

- final修饰的变量如果赋值的内容需要执行指令才能得出结果,会执行clinit方法进行初始化

小结
- 加载:根据类的全限定名把字节码文件的内容加载并转换成合适的数据放入内存中,存放在方法区和堆上
- 02连接-验证:魔数、版本号等验证,一般不需要程序员关注
- 02连接-准备:为静态变量分配内存并设置初始值
- 02连接-解析:将常量池中的符号引用(编号)替换为直接引用(内存地址)
- 03-初始化:执行静态代码块和静态变量的赋值
几个要点:
1.静态变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化
(除非要执行方法)。
2.直接访问父类的静态变量,不会触发子类的初始化。子类的初始化cinit调用之前,
会先调用父类的cinit初始化方法。
添加-XX:+TraceClassLoading 参数可以打印出加载并初始化的类
- 04-使用
- 05-卸载
相关文章:
【JVM从入门到实战】(四)类的生命周期
什么是类的生命周期 类的生命周期描述了一个类加载、连接、初始化、使用、卸载的整个过程 一个类完整的生命周期如下: 加载阶段 加载阶段第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息。 程序员可以使用Java代码拓展的不同的渠道…...
2023年度美食关键词-葱油花卷
2023年即将过去了,总结这一年的美食关键词,对于我来就,应该就是-大葱了。 前一周,朋友送了我5大葱,在北方,大葱是家家户户必不可少的食材,尤其对于面食爱好者来说,大葱的加入无疑让…...
「Verilog学习笔记」简易秒表
专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点,刷题网站用的是牛客网 timescale 1ns/1nsmodule count_module(input clk,input rst_n,output reg [5:0]second,output reg [5:0]minute);always (posedge clk or negedge rst_n) begin if (~rst…...
《每天一个Linux命令》 -- (12) file命令
欢迎阅读《每天一个Linux命令》系列 !在本篇文章中,将说明file命令用法。 概念 file命令是Linux系统下的文件类型识别命令,用于识别文件的类型。 命令操作 file命令的语法如下: file [选项] 文件命令详细解释 以下是 file 命…...
如何使用ArcGIS Pro制作类似CAD的尺寸注记
经常使用CAD制图的朋友应该比较熟悉CAD内的尺寸标注,这样的标注看起来直观且简洁,那么在ArcGIS Pro内能不能制作这样尺寸注记呢,答案是肯定的,这里为大家介绍一下制作的方法,希望能对你有所帮助。 数据来源 本教程所…...
Go语言bufio包的使用
准备文本文件 rpc_intro.txt RPC(Remote Procedure Call,远程过程调用)是一种计算机通信协议, 允许调用不同进程空间的程序。RPC 的客户端和服务器可以在一台机器上,也可以在不同的机器上。程序员使用时,就像调用本地程序一样&…...
计算机网络之IP篇
来源自小林Coding博客,阅读后部分精简笔记 目录 一、IP 的基本认识 二、DNS 三、ARP 四、DHCP 五、NAT 六、ICMP 七、IGMP 七、ping 的工作原理 ping-----查询报文的使用 traceroute —— 差错报文类型的使用 八、断网了还能 ping 通 127.0.0.1 吗&…...
Java中JDK类库常用的6种设计模式
Java中JDK类库常用的6种设计模式:1、抽象工厂。2、建造者模式。3、工厂模式。4、原型模式。5、单例模式。6、适配器模式。 1、抽象工厂 javax.xml.parsers.DocumentBuilderFactory抽象类。 public static DocumentBuilderFactory newInstance()方法。 类功能&…...
C++ 用法全面剖析
我们知道,参数的传递本质上是一次赋值的过程,赋值就是对内存进行拷贝。所谓内存拷贝,是指将一块内存上的数据复制到另一块内存上。 对于像 char、bool、int、float 等基本类型的数据,它们占用的内存往往只有几个字节,对…...
数据库结构
三级结构 内模式:也称为物理模式,它是数据库中数据的物理存储表示,描述了数据在存储介质上的存储方式和物理结构,通常由数据库管理员进行定义。 概念模式:也称为逻辑模式,它是对数据库中全体数据的逻辑表示…...
什么是HTML以及超链接,特殊符号转义的简单使用
目录 什么是HTML🌸 HTML版本 版本说明🌸 XHTML和HTML的区别 超链接🌸基本语法🌸链接的分类 特殊符号 什么是HTML HTML 不是编程语言,没有逻辑处理能力,没有计算能力,不能动态地生成内容&#x…...
汽车销售技巧培训应该学习哪些内容
汽车销售技巧培训应该学习哪些内容 随着汽车市场的竞争日益激烈,汽车销售技巧培训对于提高销售人员的销售能力和服务水平至关重要。本文将介绍汽车销售技巧培训应该学习哪些内容,并结合案例进行分析。 一、产品知识 作为销售人员,了解所销售…...
机器学习---Adaboost算法
1. Adaboost算法介绍 Adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器),然 后把这些弱分类器集合起来,构成一个更强的最终分类器(强分类器)。Adaboost算法本身…...
Java网络编程,使用UDP实现TCP(三), 基本实现四次挥手
简介 四次挥手示意图 在四次挥手过程中,第一次挥手中的Seq为本次挥手的ISN, ACK为 上一次挥手的 Seq1,即最后一次数据传输的Seq1。挥手信息由客户端首先发起。 实现步骤: 下面是TCP四次挥手的步骤: 第一次挥手&…...
“百里挑一”AI原生应用亮相,百度智能云千帆AI加速器首个Demo Day来了!
作者简介: 辭七七,目前大二,正在学习C/C,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: 七七的闲谈 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖…...
PyTorch深度学习实战(25)——自编码器
PyTorch深度学习实战(25)——自编码器 0. 前言1. 自编码器2. 使用 PyTorch 实现自编码器小结系列链接 0. 前言 自编码器 (Autoencoder) 是一种无监督学习的神经网络模型,用于数据的特征提取和降维,它由一个编码器 (Encoder) 和一…...
靠谱的车- 华为OD统一考试(C卷)
靠谱的车- 华为OD统一考试(C卷) OD统一考试(C卷) 分值: 100分 题解: Java / Python / C 题目描述 程序员小明打了一辆出租车去上班。出于职业敏感,他注意到这辆出租车的计费表有点问题…...
Apache Flink(十一):Flink集群部署-Standalone集群部署
🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录 1. 节点划分...
vue的组件传值
Vue中组件之间的数据传递可以使用props和$emit来实现。 1.使用props传递数据:父组件可以通过子组件的props属性向子组件传递数据。 父组件中: <template><div><child-component :message"parentMessage"></child-comp…...
ue5材质预览界面ue 变黑
发现在5.2和5.1上都有这个bug 原因是开了ray tracing引起的,这个bug真是长时间存在,类似的bug还包括草地上奇怪的影子和地形上的影子等等 解决方法也很简单,就是关闭光追(不是…… 就是关闭预览,在材质界面preview sc…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
【若依】框架项目部署笔记
参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...
Python环境安装与虚拟环境配置详解
本文档旨在为Python开发者提供一站式的环境安装与虚拟环境配置指南,适用于Windows、macOS和Linux系统。无论你是初学者还是有经验的开发者,都能在此找到适合自己的环境搭建方法和常见问题的解决方案。 快速开始 一分钟快速安装与虚拟环境配置 # macOS/…...
