3. 类的生命周期

news2024/11/15 22:45:40

类的生命周期是指一个类被加载,使用,卸载的一个过程,如下图:
在这里插入图片描述

类的加载阶段:

  1. 加载(Loading)阶段第一步是类加载器根据类的**全限定名(也就是类路径)**通过不同的渠道以二进制流的方式获取字节码信息。程序员可以通过Java代码来扩展不同的渠道(后面会有讲解),可以使用以下几种渠道:

    1. 本地文件
    2. 动态代理生成(类加载器是如何加载动态代理生成的class 的)
    3. 网络传输的类
  2. 类加载器在加载完类之后,Java虚拟机会将字节码中的信息保存到方法区(jdk8之后好像叫元空间)中。

    疑问:为什么类的字节码信息是保存到方法区中?方法区不应该只保存和方法有关的内容么

    解答:方法区只是一个名字,并不一定全都是保存方法信息的

  3. 在方法区中生成一个InstanceKlass对象,保存类的所有信息,里边还包含实现特定功能比如多态的信息。该对象中包含:

    1. 基本信息
    2. 常量池
    3. 字段
    4. 方法
    5. 虚方法表
  4. 同时,Java虚拟机还会在堆中生成一份与方法区中数据类似的java.lang.Class对象。作用是在Java代码中去获取类的信息以及存储静态字段的数据(JDK8及之后)。java.lang.Class对象通过一个引用和InstanceKlass对象彼此关联,例如:在使用反射的时候要通过class来获取字段名称,方法等相关信息,这个就是为什么要生成java.lang.Class对象的原因:

    InstanceKlass和java.lang.Class对象的区别?

    在Java虚拟机中InstanceKlass和java.lang.Class这两个对象都记录了类的一些信息,java.lang.Class对象中的信息要少于InstanceKlass中的信息,java.lang.Class对象只记录字段,方法等相关信息不记录多余的信息,例如: InstanceKlass中的虚方法表,这张表是Java虚拟机底层在实现多态的时候去使用的,而对于开发者信息这块儿的内容是完全不需要去使用的,所以从安全性去考虑,则将InstanceKlass对象中开发人员需要的相关参数拷贝到java.lang.Class对象中,以防止误操作

    在这里插入图片描述

查看内存中的对象

可以使用下图中的工具(看了下jdk11和jdk17 目录下都没有应该需要单独下载,只有jdk8有,应该是版本的变动导致的)

java -cp sa-jdi.jar sun.jvm.hotspot.HSDB

类加载机制的连接阶段

连接阶段分为三部分:验证,准备,解析

在这里插入图片描述

验证阶段

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

  1. 文件格式验证,比如文件是否以OxCAFEBABE开头,主次版本号是否满足当前Java虚拟机版本要求。
    • 验证字节码文件的结构是否符合Class文件格式的规范。
    • 检查文件的魔数(0xCAFEBABE)、版本号等基本信息是否正确。
  2. 元信息验证,验证Java语法是否正确
    • 验证类的元数据信息是否符合Java语言规范。例如:把Integer 写成了integer,其实就是校验Java语法
    • 包括对类、字段、方法等结构的验证,确保没有重复定义,类型描述符是否合法等。
  3. 字节码验证:
    • 栈的数据类型和操作码是否与操作参数符合:主要验证栈的数据类型所需要的空间是否超出,例如:栈有四个操作字节的空间(),但是实际占用的空间远远大于四个字节,这时在验证阶段就会报错
    • 字节码验证能否跳转到合适的位置,例如:整个字节码只有100行,而有个指令要求跳转到101行,在验证阶段就会报错
  4. 符号引用验证:
    • 某些字段或者变量是否存在访问权限,例如是否访问了其他类中private的方法等。
    • 验证符号引用是否可以解析为实际存在的类、字段和方法。
    • 确保符号引用的类型、方法签名等符合Java语言规范,确保在运行时能够正确解析和链接。

例如版本号的检测:

准备阶段

准备阶段只会给静态变量赋初始值,而每一种基本数据类型和引用数据类型都有其初始值。例如:int 类型的初始值为0


但是如果使用final 进行修饰的变量进行赋值则会在编译期(就是Java文件转换为class 文件后,字节码文件中就已经确定静态变量的值了)就可以确定静态变量的值(如下所示):

这个有个问题,下面的代码时成员变量,如果非成员变量的情况下准备阶段是否也能在编译器就确定某些变量的值(应该是可以的,回头用Java命令确定一下)

public class Student{
    public static final int value =1;
}

解析阶段

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

  1. **符号引用:**符号引用这里还不是很清晰,回头找找资料
  2. **直接引用:**直接引用则是有具体引用地址的指针,被引用的类、方法或者变量已经被加载到内存中。

类的生命周期初始化阶段

准备阶段和初始化阶段的区别

初始化阶段会执行静态代码块中的代码,并为静态变量赋值,这里和之前准备阶段的赋值时有区别的,准备阶段是给变量赋默认值,例如:

public static int value = 1;

这段代码在准备阶段的值是0因为int 类型没有赋值之前的值默认都为0,而在初始化阶段才会把当前的真正将1的值赋值给value字段。


init 指令

该指令是构造方法的指令


clinit指令

初始化阶段会执行字节码文件中clinit部分的字节码指令,这里的clinit 中cl 代表类(class),而init 代表初始化,所以这里代表的就是类的初始化,所以初始化阶段执行的就是字节码文件中的clinit部分的指令


静态代码块执行顺序问题

有这样一段代码:

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

}

这段代码的字节码指令:

0 iconst_1
1 putstatic #2 <com/jvm/Test.value : I>
4 iconst_2
5 putstatic #2 <com/jvm/Test.value : I>
8 return

此时我们发现最后value字段的值是2,如果此时我们将静态代码块往上移动:

static {
    value = 2;
}
public static int value = 1;

public static void main(String[]args){

}

下面是上面代码的字节码指令,我们会发现最后value 字段的值为1,所以这里可以看出字节码指令clinit的执行顺和Java代码中的代码顺序是一致的:

0 iconst_2
1 putstatic #2 <com/jvm/Test.value : I>
4 iconst_1
5 putstatic #2 <com/jvm/Test.value : I>
8 return


添加-XX:TraceClassLoading参数可以打印出加载并初始化的类,以下几种方式会导致类的初始化:

  1. 访问一个类的静态变量或者静态方法,注意变量是final修饰的并且等号右边是常量是不会触发初始化,而是在连接阶段直接变量进行赋值
  2. 调用Class.forName(String className),该方法有一个重载方法可以传入一个false 参数不让该方法进行初始化
  3. new一个该类的对象时
  4. 执行main方法的当前类

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

  1. 无静态代码块且无静态变量赋值语句。
  2. 有静态变量的声明,但是没有赋值语句。例如:
    public static int a;
    
  3. 静态变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化。
    public final static int a = 10;
    

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

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

相关文章

ClkLog:开源用户行为分析框架,让数据分析更轻松

ClkLog&#xff1a;开源用户行为分析框架&#xff0c;让数据分析更轻松 在数据驱动的时代&#xff0c;找到一个好用的用户行为分析工具真是难上加难。但是今天你有福了&#xff0c;开源免费的 ClkLog 就是你的不二选择&#xff01;本文将为你详细介绍 ClkLog 的功能特点、技术架…

OpenCV 彩色直方图

彩色直方图 &#xff08;1&#xff09;直方图是图像中像素强度分布。 &#xff08;2&#xff09;直方图统计了每一个强度值所具有的像素个数。 &#xff08;3&#xff09;cv2.calcHist(images, channels, mask, histSize, ranges) import cv2 import matplotlib.pyplot as …

2023年系统架构设计师考试总结

原文链接&#xff1a;https://www.cnblogs.com/zhaotianff/p/17812187.html 上周六参加了2023年系统架构设计师考试&#xff0c;这次考试与以前有点区别&#xff0c;是第一次采用电子化考试&#xff0c;也是教材改版后的第一次考试。 说说考前准备&#xff1a;为了准备这次考试…

cadence SPB17.4 - allegro - DRC error “Line to SMD Pin Same Net Spaing“

文章目录 cadence SPB17.4 - allegro - DRC error "Line to SMD Pin Same Net Spaing"概述笔记END cadence SPB17.4 - allegro - DRC error “Line to SMD Pin Same Net Spaing” 概述 铺铜前DRC正确。 铺铜后&#xff0c;报错 DRC error “Line to SMD Pin Same …

Squeeze-and-Excitation Networks

1、引言 论文链接&#xff1a;Squeeze-and-Excitation Networks (thecvf.com) 为了提高 CNN(convolutional neural network) 的表示能力&#xff0c;最近的几种方法已经显示出增强空间编码的好处。而 Jie Hu[1] 等专注于通道关系并提出了 SE(Squeeze and Excitation) 块&#x…

uniapp 使用css实现大转盘

思路&#xff1a; 1.一个原型的外壳包裹 2.使用要分配的个数&#xff0c;计算出角度&#xff0c;利用正切函数tan计算出角度对应对边长度 3.使用clip-path画出一个扇形 4.使用v-for循环出对应的份数&#xff0c;依次使用transform rotate旋转对应的角度。 注意&#xff1a…

DM集群的高可用的配置方式(多语言)

一、介绍 强调以下&#xff1a;dm_svc.conf必须放置到应用服务器上才行&#xff0c;放到其他服务器上识别不到。 文章中有的框架可能没写到并不代表不支持&#xff0c;有没提到的可文章下方留言。 1.dm_svc.conf的作用&#xff1a; dm_svc.conf文件主要是为了当DM数据库集群…

ES(ElasticSearch)倒排索引

目录 正排与倒排索引 1.正排索引 作用&#xff1a; 优点&#xff1a; 缺点&#xff1a; 2.倒排索引 原理&#xff1a; 倒排索引的构建流程&#xff1a; 倒排索引的搜索流程&#xff1a; 优点&#xff1a; 缺点&#xff1a; 3. 应用场景 倒排索引中有几个非常重要的概念…

Skyeye云智能制造企业版源代码全部开放

智能制造一体化管理系统 [SpringBoot2 - 快速开发平台]&#xff0c;适用于制造业、建筑业、汽车行业、互联网、教育、政府机关等机构的管理。包含文件在线操作、工作日志、多班次考勤、CRM、ERP 进销存、项目管理、EHR、拖拽式生成问卷、日程、笔记、工作计划、行政办公、薪资模…

【图文详解】Spring是如何解决循环依赖的?

Spring是如何解决循环依赖的呢&#xff1f; 很多小伙伴在面试时都被问到过这个问题&#xff0c;刷到过这个题的同学马上就能回答出来&#xff1a;“利用三级缓存”。面试官接着追问&#xff1a;“哪三级缓存呢&#xff1f;用两级行不行呢&#xff1f;” 这时候如果没有深入研究…

AI副业赚钱免费资源大汇总

在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;的热潮无处不在&#xff0c;许多人对于如何利用AI技术来创造收入机会感到好奇。本文将介绍一个名为aimoneyhunter的开源项目&#xff0c;这是一个专注于AI副业赚钱的资源汇总&#xff0c;旨在帮助人们在AI时代找…

技术干货 | 针对Spring-Boot 框架漏洞的初探

0x1 前言 这篇文章主要是给师傅们介绍下Spring-Boot 框架漏洞的打法以及主要对于Spring-Boot漏洞的接口泄露信息进行一个分析&#xff0c;后面使用了曾哥的Spring-Boot漏洞扫描工具&#xff0c;可以很大减轻我们对于这个漏洞接口的分析。 0x2 Spring框架简述 Spring是一个ja…

Ollama 在Windows Server 2019中部署 qwen:4b

1、环境 1.1、Ollama 1.2、Windows Server 2019 1.3、qwen:4b 1.4、nginx-1.27.0 2、部署后效果如下。 3、环境安装包下载链接包含本文所有的配置内容。 https://download.csdn.net/download/xingchengaiwei/89571623 4、安装ollama&#xff0c;官网下载地址Download Ollama…

【SpringCloud】企业认证、分布式事务,分布式锁方案落地-2

目录 高并发缓存三问 - 穿透 缓存穿透 概念 现象举例 解决方案 缓存穿透 - 预热架构 缓存穿透 - 布隆过滤器 布隆过滤器 布隆过滤器基本思想​编辑 了解 高并发缓存三问 - 击穿 缓存击穿 高并发缓存三问 - 雪崩 缓存雪崩 解决方案 总结 为什么要使用数据字典&…

一文带你了解RAG(检索增强生成) | 概念理论介绍+ 代码实操

一、LLMs 已经具备了较强能力了&#xff0c;为什么还需要 RAG(检索增强生成)? 尽管 LLM 已展现出显著的能力&#xff0c;但以下几个挑战依然值得关注&#xff1a; 幻觉问题&#xff1a;LLM 采用基于统计的概率方法逐词生成文本&#xff0c;这一机制内在地导致其可能出现看似逻…

PPT模板替换秘籍:一键撤销原模板,轻松更换新风格!

将PPT中的模板换成另一个模板&#xff0c;可以通过几种不同的方法实现。以下是几种常用的方法&#xff1a; 方法一&#xff1a;使用PowerPoint内置的设计选项卡 打开PowerPoint&#xff1a;首先&#xff0c;打开你想要更改模板的PPT文件。 选择“设计”选项卡&#xff1a;在…

Python设计模式 - 工厂方法模式

定义 工厂方法模式是一种创建型设计模式&#xff0c;它定义一个创建对象的接口&#xff0c;让其子类来处理对象的创建&#xff0c;而不是直接实例化对象。 结构 抽象工厂&#xff08;Factory&#xff09;&#xff1a;声明工厂方法&#xff0c;返回一个产品对象。具体工厂类都…

【学术会议征稿】2024年第七届机械工程与智能制造国际会议(WCMEIM 2024)

2024年第七届机械工程与智能制造国际会议&#xff08;WCMEIM 2024&#xff09; 2024 7th World Conference on Mechanical Engineering and Intelligent Manufacturing WCMEIM会议属一年一度的国际学术盛会。因其影响力及重要性&#xff0c;WCMEIM会议自创建筹办以来&#xff…

i 评论,网页评论插件使用示例

网页快速实现评论功能&#xff0c;i 评论插件&#xff0c;来试试吧&#xff01; https://andi.cn/page/621617.html

生成模型 VQVAE:Neural Discrete Representation Learning

注&#xff1a;加粗下划线名词详解见文章末 了解VQGAN之前&#xff0c;还学习了VQVAE&#xff08;Vector QuantisedVariational AutoEncoder&#xff09;&#xff09;这篇论文Neural Discrete Representation Learning&#xff0c;看了几个不错的学习视频 进行了深入了解 VQVAE…