JVM 虚拟机(二)类的生命周期

类的声明周期描述了一个类加载、使用和卸载的整个过程。
一个类的声明周期包括五个阶段:加载、连接、初始化、使用、卸载,其中连接部分分为验证、准备和解析阶段。

加载阶段

  1. 加载阶段是第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码文件 。
    1. 不同的渠道比如有:本地的文件、通过动态代理生成的类、通过网络传输的类(早期 Applet 技术使用)。
  2. 类加载器在加载完类之后,Java 虚拟机会讲字节码中的信息保存到方法区
  3. 生成一个 InstanceKlass 对象,保存类的所有信息,其中还包含实现特定功能比如多态的信息。
    1. 一个类有基本信息、常量池、字段、方法、虚方法表(多态)
  4. 同时,Java 虚拟机会在中声称一份与方法区中数据类似的
    java.lang.Class对象。可以在代码中获取类的信息以及存储静态字段的数据。

image.png

连接阶段

验证阶段

  1. 连接的第一个阶段是验证,验证的主要目的是检测 Java 字节码文件是否遵守了《Java 虚拟机规范》中的约束。这个阶段一般不需要程序员的参与
  2. 主要包含如下四种部分:
    1. 文件格式的验证,比如文件是否是以 0xCAFEBABE 开头的,主次版本号是否符合当前虚拟机版本的要求
    2. 元信息验证,例如类必须有父类(super 不能为空)
    3. 验证程序执行指令的语义,比如方法内的指令中跳转到不正确的位置
    4. 符号引用验证,比如是否访问了其他类的 private 方法等

image.png

准备阶段

准备阶段为静态变量(static)分配内存并设置初始值
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
基本类型的初始值
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
但如果基本数据类型是 final修饰的化,准备阶段会讲代码中的值进行赋值

解析

解析阶段主要是讲常量池中的符号引用替换成直接引用
符号应用就是在字节码文件中使用编号来访问常量池中的内容
image.png
转换成内存的地址来进行直接引用
image.png

初始化阶段

执行流程

初始化阶段会执行静态代码块中的代码,并且为静态变量赋值
初始化阶段会执行字节码文件中 clinit 部分的字节码指令
image.png
image.png
通过查看 clinit 中的字节码指令,可以看出在初始化阶段的执行流程:

iconst_1 // 先将 1 放到操作数栈
putstatic #2 // 将操作数栈中的值放到静态变量 valuie 中
// 静态代码块
iconst_2 // 将 2 放到操作数栈
putstatic #2 // 将操作数栈中的数放到 value 中
return

需要注意的是 clinit 中的方法的执行顺序是和 Java 中编写的顺序是一致的

类初始化的条件

  1. 访问一个类的静态变量或者静态方法,注意变量是 final 修饰的时候等号右边是变量不会触发初始化(final 在连接阶段的准备阶段就已经被赋值)
  2. 调用 Class.forName(String className)
  3. new 关键字来创建一个对象的时候
  4. 执行 Main 方法的当前类(程序的入口)

访问一个类的静态变量或者静态方法

package com.kq.init;

public class ways {
    public static void main(String[] args) {
        System.out.println(Demo01.i);
        System.out.println(Demo02.i);
    }
}
class Demo01 {
    static {
        System.out.println("Demo01类被初始化了");
    }
    public static int i = 0;
}
class Demo02 {
    static {
        System.out.println("Demo02类被初始化了");
    }
    public final static int i = 0;
}

运行结果:

Demo01类被初始化了
0
0

其他方法

package com.kq.init;

public class ways {
    static {
        System.out.println("主方法的类被初始化");
    }
    public static void main(String[] args) throws ClassNotFoundException {

//        System.out.println(Demo01.i);
//        System.out.println(Demo02.i);
        Class<?> aClass = Class.forName("com.kq.init.Demo02");
        Demo01 demo01 = new Demo01();

    }
}
class Demo01 {
    static {
        System.out.println("Demo01类被初始化了");
    }
    public static int i = 0;
}
class Demo02 {
    static {
        System.out.println("Demo02类被初始化了");
    }
    public final static int i = 0;
}

运行结果:

主方法的类被初始化
Demo02类被初始化了
Demo01类被初始化了

image.png
image.png
clinit 指令在特定的情况下不会出现,比如:

  1. 无静态代码块且无静态变量的赋值语句
  2. 有静态变量的声明但是没有赋值语句
  3. 静态变量的定义使用 final 关键字,这类变量会在准备阶段直接进行初始化
  4. 在子类直接访问父类中的静态变量,不会触发子类的初始化
    1. 子类的初始化在 clinit 调用之前会先调用父类的 clinit 方法

在这三种情况初始化不会执行0

package com.kq.init;

public class extend {
    public static void main(String[] args) {
        System.out.println(Son.i);
    }
}
class Father {
    public static int i;
}
class Son extends Father {
    static {
        System.out.println("子类被初始化");
    }

}

运行结果:

0

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CAN总线协议编程实例

1. can.h #ifndef __CAN_H #define __CAN_H#include "./SYSTEM/sys/sys.h"/******************************************************************************************/ /* CAN 引脚 定义 */#define CAN_RX_GPIO_PORT GPIOA #define CAN_RX_GPI…

【Maven】未找到有效的 Maven 安装。在配置对话框中设置主目录,或者在系统上设置 M2_HOME 环境变量。

错误显示 今天导入工程&#xff0c;进行clean的时候报错&#xff1a; 解决方法 重新设置一下maven的目录即可

微机原理14

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中选出一个正确的答案,请将选定的答案填涂在答题纸的相应位置上。) 字符’A’的 ASCI 码是&#xff08;&#xff09; A. OAH B. 41H C. 61H D. OAOH 2, 8086微处理器的地址线有(&#xff09; A. 16条…

RabbitMQ-学习笔记(初识 RabbitMQ)

本篇文章学习于 bilibili黑马 的视频 (狗头保命) 同步通讯 & 异步通讯 (RabbitMQ 的前置知识) 同步通讯&#xff1a;类似打电话&#xff0c;只有对方接受了你发起的请求,双方才能进行通讯, 同一时刻你只能跟一个人打视频电话。异步通讯&#xff1a;类似发信息&#xff0c…

根据既定数组创建数组的方法汇总 (第3讲)

根据既定数组创建数组的方法 &#xff08;第3讲&#xff09;         &#x1f379;博主 侯小啾 感谢您的支持与信赖。☀️ &#x1f339;꧔ꦿ&#x1f339;꧔ꦿ&#x1f339;꧔ꦿ&#x1f339;꧔ꦿ&#x1f339;꧔ꦿ&#x1f339;꧔ꦿ&#x1f339;꧔ꦿ&#x1f339;꧔…

2021年第十届数学建模国际赛小美赛A题气道阻力的评估解题全过程文档及程序

2021年第十届数学建模国际赛小美赛 A题 气道阻力的评估 原题再现&#xff1a; 气道阻力的定义是通过肺气道产生单位气流所需的经肺压力的变化。更简单地说&#xff0c;它是嘴和肺泡之间的压力差&#xff0c;除以气流。影响气道阻力的因素是多方面的&#xff0c;我们需要探讨这…

python 数据分析

数据分析 数据分析是指用适当的方法对收集的数据进行分析,提取有用信息并且形成结论. 广义的数据分析包括狭义的数据分析和数据挖掘.狭义的数据分析是指根据目的,采用对比分析,分组分析,交叉分析,回归分析等分析方法,对数据进行分析和处理,得到特征统计量的过程.数据挖掘是指…

20231207给NanoPC-T4(RK3399)开发板刷Android12的挖掘机方案的LOG

20231207给NanoPC-T4(RK3399)开发板刷Android12的挖掘机方案的LOG 2023/12/7 23:50 SDK&#xff1a;rk356x_android12_220722.tgz 只修改DTS的DTC部分就【直接】可以跑NanoPC-T4 参考资料&#xff1a; http://www.friendlyelec.com.cn/agent.asp http://www.friendlyelec.com.c…

[FPGA 学习记录] 快速开发的法宝——IP核

快速开发的法宝——IP核 文章目录 1 IP 核是什么2 为什么要使用 IP 核3 IP 核的存在形式4 IP 核的缺点5 Quartus II 软件下 IP 核的调用6 Altera IP 核的分类 在本小节当中&#xff0c;我们来学习一下 IP 核的相关知识。 IP 核在 FPGA 开发当中应用十分广泛&#xff0c;它被称为…

Spark RDD惰性计算的自主优化

原创/朱季谦 RDD&#xff08;弹性分布式数据集&#xff09;中的数据就如final定义一般&#xff0c;只可读而无法修改&#xff0c;若要对RDD进行转换或操作&#xff0c;那就需要创建一个新的RDD来保存结果。故而就需要用到转换和行动的算子。 Spark运行是惰性的&#xff0c;在…

UE Http笔记

c参考链接 UE4 开发如何使用 Http 请求_wx61ae2f5191643的技术博客_51CTO博客 虚幻引擎:UEC如何对JSON文件进行读写?-CSDN博客 UE4 HTTP使用 官方免费插件 VaRest 在代码插件创建的VaRest - 虚幻引擎商城 UE5在蓝图中使用Varest插件Get&#xff0c;Post两种常见请求方式…

C# Solidworks二次开发:三种获取SW设计结构树的方法-第二讲

今天这篇文章是接上一篇文章的&#xff0c;主要讲述的是获取SW设计结构树节点的第二种方法。 这个方法获取节点的逻辑是先获取最顶层节点&#xff0c;然后再通过获取顶层节点的子节点一层一层的把所有节点都找出来&#xff0c;也就是需要递归。想要用这个方法就要了解下面几个…

常见的校验码

在计算机领域中&#xff0c;校验码是一种用于检测或纠正数据传输或存储中错误的技术。校验码通常通过在数据中添加一些冗余信息来实现。其主要目的是确保数据的完整性和准确性。 奇偶校验码&#xff08;Parity Check&#xff09; 奇校验&#xff1a; 确保数据中二进制位中的1的…

JWT安全及WebGoat靶场

JWT 安全 cookie(放在浏览器) cookie 是一个非常具体的东西&#xff0c;指的就是浏览器里面能永久存储的一种数据&#xff0c;仅仅是浏览器实现的一种数据存储功能。 cookie 由服务器生成&#xff0c;发送给浏览器&#xff0c;浏览器把 cookie 以 kv 形式保存到某个目录下的…

文件同步及实现简单监控

1. 软件简介 rsync rsync 是一款开源的、快速的、多功能的、可实现全量及增量的本地或远程 数据同步备份的优秀工具。在同步备份数据时&#xff0c;默认情况下&#xff0c;Rsync 通过其 独特的“quick check”算法&#xff0c;它仅同步大小或者最后修改时间发生变化的文 件或…

CentOS上配置和管理HTTP服务器的工具和实用程序

在CentOS系统上&#xff0c;有多个工具和实用程序可以帮助你配置和管理HTTP服务器。以下是一些常用的工具和实用程序&#xff1a; Apache HTTP服务器&#xff1a; Apache是CentOS上最常用的HTTP服务器之一。它是一个开源的Web服务器软件&#xff0c;具有高度的可配置性和可扩…

在jupyter notebook中修改其他文件的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

dell服务器安装PERCCLI

因在linux 系统中无法查看系统磁盘的raid级别&#xff0c;也无法得知raid状态&#xff0c;需要安装额外的包来监控&#xff0c;因是dell服务器&#xff0c;就在dell网站中下载并安装 1、下载链接&#xff1a;驱动程序和下载 | Dell 中国https://www.dell.com/support/home/zh-…

ELK(四)—els基本操作

目录 elasticsearch基本概念RESTful API创建非结构化索引&#xff08;增&#xff09;创建空索引&#xff08;删&#xff09;删除索引&#xff08;改&#xff09;插入数据&#xff08;改&#xff09;数据更新&#xff08;查&#xff09;搜索数据&#xff08;id&#xff09;&…

查看端口号是否被占用

windows10查看端口号是否被占用及解除占用的常用命令 netstat -ano&#xff1a;查看所有端口号占用情况 netstat -ano |findstr “XXX”&#xff1a;查看端口号为XXX的占用情况&#xff0c;如下&#xff1a; 得到进程号为12160的进程正在占用本地的9090端口号&#xff08;如果只…