jvm--类的生命周期

ops/2025/2/3 16:54:17/

学习类的生命周期之前,需要了解一下jvm的几个重要的内存区域:

(1)方法区:存放已经加载的类信息、常量、静态变量以及方法代码的内存区域

(2)常量池:常量池是方法区的一部分,用来存放常量和类中的符号引用等信息

(3)堆区:用来存放类的对象实例

(4)栈区:栈区是由一个个栈桢组成的后进先出的栈式结构,栈桢里面存放的是运行时产生的局部变量、方法出口等信息。当调用一个方法时,jvm就会创建一个栈桢存放这些数据,当这些方法调用完成后,栈桢就会消失。如果方法中调用了其他的方法时,就会在栈顶创建新的栈顶。

类的生命周期

       编译完成java源码后,生成一个class文件,只有这种字节码文件才能在jvm上运行,类的生命周期就是指一个class文件从加载到卸载的全过程。

        一个类的完整生命周期会经历加载、连接、初始化、使用和卸载五个阶段,也有加载或者链接之后就被直接使用的情况。

加载

        这里的加载和类加载不一样,类加载是指加载、连接和初始化这三个阶段。

        加载是先获取字节码文件的信息,找到需要加载的类并把类的信息加载到方法区,然后在堆区实例化一个java.lang.class对象,作为方法区中这个类的信息的入口。

        加载的具体步骤:

                (1)类加载器根据类的全限定名通过不同渠道(磁盘、运行时动态代理、网络)以二进制流的方式获取字节码信息;

                (2)类加载器在加载完类后,java虚拟机会将字节码文件的信息保存在方法区;

                (3)在方法区生成一个InsanceKlass对象,保存类的所有信息,里面还包含实现特定功能比如多态的信息(虚方法表)。

                (4)java虚拟机同时会在堆上生成与方法区数据类似的java.lang.class对象,作用是java代码中获取类的信息以及存储静态字段的数据

        问题:java.lang.class和InstanceKlass既然类似,为什么还要生成?

        (1)InstanceKlass是c++源码,而java.lang.class对象是java代码,class在java中可以直接调用;

        (2)静态字段的值是存放在堆区的java.lang.class里面的;

        (3)java.lang.class对象里面的信息只是一部分,InstanceKlass里面的信息并不是一定要去使用的,开发者调用java.lang.class对象可以保证类信息的访问数据安全性

连接

        连接分为三个阶段:

      (1)验证:验证字节码文件内容(文件格式、元信息的验证、验证程序执行指令的语义、符号引用的验证)是否满足《java虚拟机的规范》

     (2)准备:给静态变量赋初值,使用final修饰的字段会附上代码里面的值,因为使用final修饰的字段到最后值不会被修改

        (3)解析:将常量池中的符号引用替换成指向内存的直接引用(使用内存地址进行访问)

初始化阶段

        在连接阶段结束后,类的信息已经加载到了内存中,同时校验等工作已经做完了。从初始化开始,就和我们开发人员有关了。在连接阶段中,非final的静态变量赋的是初值,会保存在堆的class对象里,但代码里面的值还没有附上,这个操作就是在初始化中完成。

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

        举一个例子:


public class Demo1 {public static int value = 1;static {value = 2;}public static void main(String[] args) {}
}

init方法:会在对象初始化执行;

main方法:主方法;

clinit:类的初始化阶段执行;

clinit字节码信息:

iconst_1:把常量1放进操作数栈中;

putstatic:把操作数栈里面的值弹出,并放在堆中静态变量的位置

最后value的值是2

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

        (1)访问一个类的静态变量或者静态方法,注意变量使用final修饰时,不会触发初始化这一阶段;

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

        (3)new一个类的对象时;

        (4)执行main方法的当前类;

       添加-XX:+TraceClassLoading 参数可以打印出加载并初始化的类

一下这几种情况是不会进行初始化指令执行的:

        (1)无静态代码块且无静态变量赋值语句;

        (2)有静态变量的声明,但是没有赋值语句;

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

特殊情况:

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

        (2)子类的初始化clinit调用之前,会先调用父类的clinit初始化方法;


http://www.ppmy.cn/ops/155352.html

相关文章

【React+ts】 react项目中引入bootstrap、ts中的接口

一、在react项目中引入bootstrap 这个直接用npm下载包然后在index.js中引入就可以了。 npm install bootstrap react-bootstrap后面那个必须要下载,应该有什么联动的包要用。 然后在index.tsx中引入 import "bootstrap/dist/css/bootstrap.min.css"; i…

AI大模型开发原理篇-1:语言模型雏形之N-Gram模型

N-Gram模型概念 N-Gram模型是一种基于统计的语言模型,用于预测文本中某个词语的出现概率。它通过分析一个词语序列中前面N-1个词的出现频率来预测下一个词的出现。具体来说,N-Gram模型通过将文本切分为长度为N的词序列来进行建模。 注意:这…

1.Template Method 模式

模式定义 定义一个操作中的算法的骨架(稳定),而将一些步骤延迟(变化)到子类中。Template Method 使得子类可以不改变(复用)一个算法的结构即可重定义(override 重写)该算法的某些特…

第一届“启航杯”网络安全挑战赛WP

misc PvzHE 去这个文件夹 有一张图片 QHCTF{300cef31-68d9-4b72-b49d-a7802da481a5} QHCTF For Year 2025 攻防世界有一样的 080714212829302316092230 对应Q 以此类推 QHCTF{FUN} 请找出拍摄地所在位置 柳城 顺丰 forensics win01 这个软件 云沙盒分析一下 md5 ad4…

FastDFS实用笔记 (Docker 搭建环境 + 整合 SpringBoot)

解决了大容量存储 和 负载均衡的问题&#xff0c;特别适合中小文件&#xff08;4KB < file_size < 500MB)。如相册网站&#xff0c;视频网站等 FastDFS 充分考虑了冗余备份&#xff0c;线程扩容机制&#xff0c;并注重高可用。高性能等指标。使用 FastDFS 很容易搭建一套…

Nginx 开发总结

文章目录 1. Nginx 基础概念1-1、什么是 Nginx1-2、Nginx 的工作原理1-3、Nginx 的核心特点1-4、Nginx 的常见应用场景1-5、Nginx 与 Apache 的区别1-6、 Nginx 配置的基本结构1-7、Nginx 常见指令 2. Nginx 配置基础2-1、Nginx 配置文件结构2-2、全局配置 (Global Block)2-3、…

云原生(五十三) | SQL查询操作

文章目录 SQL查询操作 一、数据库DDL操作 1、登陆数据库 2、创建DB数据库 二、数据表DDL操作 1、创建数据表 2、RDS中SQL查询操作 三、SQL查询操作 1、RDS中SQL查询操作 SQL查询操作 一、数据库DDL操作 1、登陆数据库 2、创建DB数据库 创建一个普通账号&#xff0c…

Hutool工具类

Hutool 是一个非常流行的 Java 工具类库&#xff0c;它提供了丰富的功能来简化开发中的常见任务&#xff0c;比如文件操作、加密、日期处理、字符串操作、数据库工具等。它是一个轻量级的工具库&#xff0c;可以减少开发者编写常用代码的工作量&#xff0c;提高开发效率。 主要…