3. 类的生命周期

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

类的加载阶段:

  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.mzph.cn/web/49881.shtml

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

相关文章

[C#]调用本地摄像头录制视频并保存

AForge.NET是一个基于C#框架设计的开源计算机视觉和人工智能库&#xff0c;专为开发者和研究者设计。它提供了丰富的图像处理和视频处理算法、机器学习和神经网络模型&#xff0c;具有高效、易用、稳定等特点。AForge库由多个组件模块组成&#xff0c;包括AForge.Imaging&#…

go语言day19 使用git上传包文件到github Gin框架入门

git分布式版本控制系统_git切换head指针-CSDN博客 获取请求参数并和struct结构体绑定_哔哩哔哩_bilibili &#xff08;gin框架&#xff09; GO: 引入GIn框架_go 引入 gin-CSDN博客 使用git上传包文件 1&#xff09;创建一个github账户&#xff0c;进入Repositories个人仓…

【深度学习】语音合成,TTS,fish-speech

官方项目地址&#xff1a;https://github.com/fishaudio/fish-speech git clone https://github.com/fishaudio/fish-speech.gitdocker run -it --gpus device3 -v /ssd/xiedong/tts:/ssd/xiedong/tts --net host --shm-size 16G kevinchina/deeplearning:pytorch2.3.0-cuda12.…

Matlab编程资源库(9)数据插值与曲线拟合

一、一维数据插值 在MATLAB中&#xff0c;实现这些插值的函数是interp1&#xff0c;其调用格式为&#xff1a; Y1interp1(X,Y,X1,method) 函数根据X,Y的值&#xff0c;计算函数在X1处的值。X,Y是两个等长的已知向量&#xff0c;分别描述采样点和样本值&#xff0c;X1是一个向量…

第三届人工智能、物联网和云计算技术国际会议(AIoTC 2024,9月13-15)

第三届人工智能、物联网与云计算技术国际会议(AIoTC 2024)将于2024年9月13日-15日在中国武汉举行。 本次会议由华中师范大学伍伦贡联合研究院与南京大学联合主办、江苏省大数据区块链与智能信息专委会承办、江苏省概率统计学会、江苏省应用统计学会、Sir Forum、南京理工大学、…

昇思25天学习打卡营第21天|Pix2Pix实现图像转换

相关知识 图像翻译 图像翻译Image translation是一种计算机视觉任务&#xff0c;旨在将一种图像转换为另一种图像。典型的任务包括&#xff1a;图像到图像的转换如白天到黑夜&#xff0c;风格迁移&#xff0c;图像修复。 CGAN CGAN在GAN的基础上引入了条件信息&#xff0c;…

MATLAB-bode图编程

num[1 1];den [2 1];tf(num,den)bode(tf(num,den));hold on

python selenium selenium-wire使用代理

前言 最近使用selenium、selenium-wire爬取数据&#xff0c;在使用代理时查阅很多资料&#xff0c;在使用过程中发现很多资料、博客中都是错误的用法&#xff0c;误导初学selenium使用代理的开发者 描述&#xff1a; 我这里使用的是Python 3.12.2 selenium4.23.1 seleni…

torch fbgemm.dll 报错

这里写自定义目录标题 OSError: [WinError 126] The specified module could not be found. Error loading \"c:\\Users\\Noor\\anaconda3\\envs\\DL\\Lib\\site-packages\\torch\\lib\\fbgemm.dll\" or one of its dependencies."https://github.com/lucasg/De…

uniapp小程序中富文本内容渲染图片不展示的问题

文章目录 1.从后端请求的数据中图片是这样的2.前端我是用Uview中的u-parse组件3.这样修改去掉富文本中的所有反斜杠4.完美解决 1.从后端请求的数据中图片是这样的 <p><img src\\\"https://zhangsanfengcode.cn:8084/images/2024-06-28a257befe.jpg\\\" alt…

【XML入门精要】从零开始的开发之旅

参考文档&#xff1a;XML 教程 (w3school.com.cn) 简介 XML&#xff0c;全称eXtensible Markup Language&#xff0c;即“可扩展标记语言”&#xff0c;是一种用于存储和传输数据的标准格式。它由万维网联盟&#xff08;W3C&#xff09;开发&#xff0c;目的是克服HTML&#…

【网络流】——初识(最大流)

网络流-最大流 基础信息引入一些概念基本性质 最大流定义 Ford–Fulkerson 增广Edmons−Karp算法Dinic 算法参考文献 基础信息 引入 假定现在有一个无限放水的自来水厂和一个无限收水的小区&#xff0c;他们之间有多条水管和一些节点构成。 每一条水管有三个属性&#xff1a…

如何查看cpu架构,查看CPU架构的方法

查看CPU架构的方法有很多&#xff0c;具体取决于你使用的操作系统。以下是一些常见的操作系统中查看CPU架构的方法&#xff1a; Windows查看CPU架构的方法 使用系统信息工具 按 Win R 打开运行窗口。输入 msinfo32 并按 Enter。在系统信息窗口中&#xff0c;找到“处理器”一…

懂个锤子Vue 项目工程化进阶⏫:

Vue项目工程化进阶⏫&#xff1a; 前言&#xff1a; 紧跟前文&#xff0c;目标学习Vue2.0——3.0&#xff1a; 懂个锤子Vue、WebPack5.0、WebPack高级进阶 涉及的技术栈… 当然既然学习框架的了&#xff0c;HTMLCSSJS三件套必须的就不说了&#xff1a; JavaScript 快速入门 …

7-25学习笔记

一、锁对象 Lock接口 1、创建锁对象 ReentrantLock类 Lock locknew ReentrantLock(true); 默认创建的是非公平锁 在创建锁对象时传入一个true参数 便会创建公平锁 先来后到 是重入锁 排他锁 加锁后不允许其它线程进入 2、加锁、解锁 &#xff08;1&#xff09;loc…

Redis-数据的极速之旅(一)

Redis基础篇 Redis的自我介绍我的核心数据结构1.字符串&#xff08;String&#xff09;2.哈希&#xff08;Hash&#xff09;3.列表&#xff08;List&#xff09;4.集合&#xff08;Set&#xff09;5.有序集合&#xff08;Sorted Set&#xff09; 高性能原理1.Redis为什么快&…

B端系统UI个性化设计:感受定制之美

B端系统UI个性化设计&#xff1a;感受定制之美 引言 艾斯视觉作为ui设计和前端开发从业者&#xff0c;其观点始终认为&#xff1a;在当今竞争激烈的商业环境中&#xff0c;B端&#xff08;Business-to-Business&#xff09;系统的设计不再仅仅是功能性的堆砌&#xff0c;而是…

书生大模型实战营--L1关卡-OpenCompass 评测 InternLM-1.8B 实践

一、使用 OpenCompass 评测 internlm2-chat-1.8b 模型在 MMLU 数据集上的性能 1、使用lmdeploy部署 internlm2-chat-1.8b模型 2、根据OpenCompass官网教程安装并下载数据集 opencompass/README_zh-CN.md at main open-compass/opencompass GitHub 注意&#xff1a; pyhton…

JAVAWeb实战(前端篇)

项目实战一 0.项目结构 1.创建vue3项目&#xff0c;并导入所需的依赖 npm install vue-router npm install axios npm install pinia npm install vue 2.定义路由&#xff0c;axios&#xff0c;pinia相关的对象 文件&#xff08;.js&#xff09; 2.1路由(.js) import {cre…

当全球银行系统“崩溃”时会发生什么?

有句名言&#xff1a;“当美国打喷嚏时&#xff0c;世界就会感冒……”换句话说&#xff0c;当人们对美国及其经济稳定性的信心下降时&#xff0c;其他经济体&#xff08;以及黄金、白银和股票等资产&#xff09;的价值往往会下降。 与任何其他资产类别一样&#xff0c;加密货…