JVM——类的生命周期

embedded/2025/2/21 22:38:56/

目录

生命周期的概述:

加载阶段:

连接阶段:

1、验证:

2、准备:

3、解析

初始化阶段:

总结:


类的生命周期描述了一个类加载、使用、卸载的整个过程。

生命周期的概述:

类的生命周期:
可以被看做是5个或者7个步骤
  • 加载
  • 连接*
    • 验证
    • 准备
    • 解析
  • 初始化*
  • 使用
  • 卸载

加载阶段:

1、加载阶段的第一步是 类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息(将其加载到内存中)
  • 渠道一:本地文件——磁盘上的字节码文件
  • 渠道二:动态代理——程序运行时使用动态代理生成(spring)
  • 渠道三:通过网络传输的类——小程序(被淘汰)
2、类加载器在加载完类之后,java虚拟机会将字节码中的信息保存到 方法区中。
3、类加载器在加载完类之后,java虚拟机会将字节码中的信息保存到内存的方法区中。 方法区中会生成一个 InstanceKlass对象 ,保存类的所有信息,里面还包含实现特定功能比如多态的信息
4、同时,Java虚拟机还会在堆中生成一份与方法区中数据类似的java.lang.Class对象。 作用是在Java代码中去获取类的信息以及存储 静态字段 的数据
方法区 和 堆区 的信息相互关联,可以通过一个去调用另一个。
  • 对于开发者来说,只需要访问堆中的Class对象而不需要访问方法区中的所有信息,这样java虚拟机可以很好的来控制开发者访问数据的范围
:方法区中的instanceKlass使用c++编译的,java不太好操作,所以在堆中创建了堆区中通过java语言包装后的对象(再从方法区中拷贝的过程中会将一些内容剔除掉,只包含我们需要的。是为了安全性的考虑)
全部加载到了内存中

连接阶段:

  • 验证:验证是否满足java虚拟机规范
  • 准备:给静态变量赋初值
  • 解析:将常量池中的符号引用替换成指向内存的直接引用
1、验证:
连接阶段的第一个环节是验证,验证的主要目的是检测Java字节码文件是否遵守了《Java虚拟机规范》中的约束。这个阶段不用程序员参与。
主要有四部分:
  • 魔数的校验,文件格式的校验
  • 元信息验证,例如类必须有父类
  • 验证程序执行指令的语义,比如方法内的指令执行到一半强制跳转到其他方法中去
  • 符号引用类型,例如是否访问了其它类中private的方法等。
2、准备:
准备阶段为 静态变量分配内存并 设置初始值
int
0
long
0L
short
0
char
‘\u0000’
byte
0
boolean
false
double
0.0
引用
null
定义的都是静态变量
不使用final关键字赋值的时候,会给其添加默认值(也就是上表中的数据)会被存放在 堆区的class对象中(java.lang.Class),而在 初始化阶段为其赋上真正的值。
当我定义数据时使用了final关键字,这就代表了在以后这个数据的值不再会发生变化了,所以就会在准备阶段直接将代码中的值进行赋值。他就会直接在堆区中的java.lang.Class中进行赋值了。
3、解析
  • 解析阶段主要是将常量池中的符号引用替换为直接引用。
  • 符号引用就是在字节码文件中使用编号来访问常量池中的内容。
  • 直接引用不再使用编号,而是使用内存中地址进行访问具体的数据。(性能行对较高)
我们使用jclasslib查看时可以看到使用编号号引用的信息,我们使用HSDB就可以查看到实际上使用的是内存地址的信息。

初始化阶段:

  • 初始化阶段会执行静态代码块中的代码,并为静态变量赋值
  • 其实就是 会执行字节码文件中clinit的字节码指令。【赋的值是从操作数栈中取出来的】
操作数栈:一种数据结构,用来存放参与运算的数据的临时存储区域。
clinit方法中的执行顺序与java中编写的顺序是一样的
  • 以下的几种方式会导致类的初始化
1、访问一个类的静态变量或者静态方法,注意变量是final修饰的并且等号右边是常量不会触发初始化。
2、调用Class.forName(String className)
这个方法中有两个重载方法,第一个是只传递一个参数 会默认进行初始化,第二个是可以指定是否进行初始化。
3、new一个该类的对象时。
4、执行Main方法的当前类。
  • clinit指令在特定情况下不会出现,比如:如下几种情况是不会进行初始化指令执行的。
1、无静态代码块且无静态变量赋值语句。
2、有静态变量的声名,但是没有赋值语句。
3、静态变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化。
父类——子类
  • 直接访问父类的静态变量,不会触发子类的初始化。
  • 子类的初始化clinit调用之前,会先调用父类的clinit的初始化方法。
数组的创建不会导致数组中元素的类进行初始化
final修饰的变量如果赋值的内容需要执行指令才能得出结论,会执行clinit方法进行初始化
总结:
  • 加载:根据类的全限定名吧字节码文件的内容加载并转换成合适的数据放入内存中,存放在方法区和堆上
  • 连接:
    • 验证:魔数、版本号等验证,一般不需要程序员关注
    • 准备:为静态变量分配内存并设置初始值
    • 解析:将常量池中的符号引用(编号)替换成直接引用(内存地址)
  • 初始化:执行静态代码块和静态变量的赋值
    • 金泰变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化(除非要执行方法)
    • 直接访问父类的静态变量,不会触发子类的初始化。子类的初始化cinit调用之前,会先调用父类的cinit初始化方法。

http://www.ppmy.cn/embedded/162428.html

相关文章

【第4章:循环神经网络(RNN)与长短时记忆网络(LSTM)——4.2 LSTM的引入与解决长期依赖问题的方法】

在人工智能的璀璨星空中,深度学习模型犹如一颗颗耀眼的星辰,引领着技术的革新。而在处理序列数据的领域中,循环神经网络(RNN)无疑是那颗最为亮眼的星星。然而,即便是这样强大的模型,也面临着一些棘手的问题,其中最突出的便是长期依赖问题。今天,我们就来深入探讨一下长…

无耳科技 Solon v3.0.8 发布,Java 企业级应用开发框架

Solon 框架! Solon 是新一代,Java 企业级应用开发框架。是杭州无耳科技有限公司的“根级”开源项目(最近“杭州六小龙”很火啊,我们也是杭州的哦)。从零开始构建(No Spring、No Java-EE、No Servlet&#…

Python--常见库与函数

二、Python常见库与函数 2.1 OS库 常用功能:文件/目录操作、路径管理、环境变量。 import os # 路径操作 abs_path os.path.abspath("data.txt") exists os.path.exists(abs_path) # 目录操作 os.mkdir("logs") # 创建目录(需处…

借用python 学习 VM的 FTP(VisionMaster4.3)

无懒不python:看官方V社区有介绍: 需要安装 Quick Easy FTP Server V4.0.0.exe 为了表示敬意再次放出链接: V社区-机器智能技术交流-VM关于FTP存图的一点分享 好了VM先放一边 先用python自收 自发: 毕竟这个免费 FTP服务端: 0.ftpserver.py 需要安装的库 和 注意事项已经在…

3、《Spring Boot 常见注解详解》

Spring Boot 核心注解详解 摘要 本文深入剖析 Spring Boot 常用注解,如SpringBootApplication、Controller、Service、Repository等,详细讲解它们的功能、使用场景及原理,帮助开发人员更好地理解和运用 Spring Boot 框架进行项目开发。 一…

单细胞学习(13)—— Seurat → Scanpy 分析流程

下面是一份从 Seurat 分析流程转到Scanpy 分析流程的简要笔记,涵盖了从数据读入到细胞注释的主要环节,并附上常用函数的Seurat vs. Scanpy 对照表。该笔记既可作为工作流程指南,也能在两个分析平台之间快速切换和比较。 Seurat → Scanpy 分析…

DeepSeek使用技巧大全(含本地部署教程)

在人工智能技术日新月异的今天,DeepSeek 作为一款极具创新性和实用性的 AI,在众多同类产品中崭露头角,凭借其卓越的性能和丰富的功能,吸引了大量用户的关注。 DeepSeek 是一款由国内顶尖团队研发的人工智能,它基于先进…

VSCode Error Lens插件介绍(代码静态检查与提示工具)(vscode插件)

文章目录 VSCode Error Lens 插件介绍**功能概述****开发背景****使用方法****适用场景** VSCode Error Lens 插件介绍 功能概述 Error Lens 是一款增强 VS Code 错误提示的扩展工具,通过 内联显示错误和警告信息,直接定位代码问题,提升开发…