3、类的生命周期

类的生命周期描述了一个类加载、使用、卸载的整个过程。整体可以分为:

  • 加载
  • 连接,其中又分为验证、准备、解析三个子阶段
  • 初始化
  • 使用
  • 卸载
  • 在这里插入图片描述
    2.3.1 加载阶段
    1、加载(Loading)阶段第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息,程序员可以使用Java代码拓展的不同的渠道。
  • 从本地磁盘上获取文件
  • 运行时通过动态代理生成,比如Spring框架
  • Applet技术通过网络获取字节码文件
    2、类加载器在加载完类之后,Java虚拟机会将字节码中的信息保存到方法区中,方法区中生成一个InstanceKlass对象,保存类的所有信息,里边还包含实现特定功能比如多态的信息。
    在这里插入图片描述
    4、Java虚拟机同时会在堆上生成与方法区中数据类似的java.lang.Class对象,作用是在Java代码中去获取类的信息以及存储静态字段的数据(JDK8及之后)。
    在这里插入图片描述
    2.3.2 连接阶段
    连接阶段分为三个子阶段:
  • 验证,验证内容是否满足《Java虚拟机规范》。
  • 准备,给静态变量赋初值。
  • 解析,将常量池中的符号引用替换成指向内存的直接引用。
  • 在这里插入图片描述
    验证
    验证的主要目的是检测Java字节码文件是否遵守了《Java虚拟机规范》中的约束。这个阶段一般不需要程序员参与。主要包含如下四部分,具体详见《Java虚拟机规范》:
    1、文件格式验证,比如文件是否以0xCAFEBABE开头,主次版本号是否满足当前Java虚拟机版本要求。
    在这里插入图片描述

2、元信息验证,例如类必须有父类(super不能为空)。
3、验证程序执行指令的语义,比如方法内的指令执行中跳转到不正确的位置。
4、符号引用验证,例如是否访问了其他类中private的方法等。

对版本号的验证,在JDK8的源码中如下:
在这里插入图片描述
编译文件的主版本号不能高于运行环境主版本号,如果主版本号相等,副版本号也不能超过。

准备
准备阶段为静态变量(static)分配内存并设置初值,每一种基本数据类型和引用数据类型都有其初值。
在这里插入图片描述
如下代码:

public class Student{

public static int value = 1;

}

在准备阶段会为value分配内存并赋初值为0,在初始化阶段才会将值修改为1。

final修饰的基本数据类型的静态变量,准备阶段直接会将代码中的值进行赋值。
如下例子中,变量加上final进行修饰,在准备阶段value值就直接变成1了,因为final修饰的变量后续不会发生值的变更。
在这里插入图片描述

public class HsdbDemo {
    public static final int i = 2;
    public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException {
        HsdbDemo hsdbDemo = new HsdbDemo();
        System.out.println(i);
        System.in.read();
    }
}

从字节码文件也可以看到,编译器已经确定了该字段指向了常量池中的常量2:
[图片]
解析
解析阶段主要是将常量池中的符号引用替换为直接引用,符号引用就是在字节码文件中使用编号来访问常量池中的内容。
在这里插入图片描述
直接引用不在使用编号,而是使用内存中地址进行访问具体的数据。
在这里插入图片描述
2.3.3 初始化阶段
初始化阶段会执行字节码文件中clinit(class init 类的初始化)方法的字节码指令,包含了静态代码块中的代码,并为静态变量赋值。
如下代码编译成字节码文件之后,会生成三个方法:

public class Demo1 {

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

    }
}

在这里插入图片描述

  • init方法,会在对象初始化时执行
  • main方法,主方法
  • clinit方法,类的初始化阶段执行

继续来看clinit方法中的字节码指令:
1、iconst_1,将常量1放入操作数栈。此时栈中只有1这个数。
在这里插入图片描述
2、putstatic指令会将操作数栈上的数弹出来,并放入堆中静态变量的位置,字节码指令中#2指向了常量池中的静态变量value,在解析阶段会被替换成变量的地址。
在这里插入图片描述
3、后两步操作类似,执行value=2,将堆上的value赋值为2。

如果将代码的位置互换:

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

    }
}

字节码指令的位置也会发生变化:
在这里插入图片描述
这样初始化结束之后,最终value的值就变成了1而不是2。

以下几种方式会导致类的初始化:
1.访问一个类的静态变量或者静态方法,注意变量是final修饰的并且等号右边是常量不会触发初始化。
2.调用Class.forName(String className)。
3.new一个该类的对象时。
4.执行Main方法的当前类。
添加-XX:+TraceClassLoading 参数可以打印出加载并初始化的类

面试题1:
如下代码的输出结果是什么?

public class Test1 {
    public static void main(String[] args) {
        System.out.println("A");
        new Test1();
        new Test1();
    }

    public Test1(){
        System.out.println("B");
    }

    {
        System.out.println("C");
    }

    static {
        System.out.println("D");
    }
}

分析步骤:
1、执行main方法之前,先执行clinit指令。
在这里插入图片描述
指令会输出D
2、执行main方法的字节码指令。
在这里插入图片描述
指令会输出A
3、创建两个对象,会执行两次对象初始化的指令。
在这里插入图片描述
这里会输出CB,源代码中输出C这行,被放到了对象初始化的一开始来执行。
所以最后的结果应该是DACBCB

clinit不会执行的几种情况
如下几种情况是不会进行初始化指令执行的:
1.无静态代码块且无静态变量赋值语句。
2.有静态变量的声明,但是没有赋值语句。
在这里插入图片描述
3.静态变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化。
在这里插入图片描述
面试题2:
如下代码的输出结果是什么?

public class Demo01 {
    public static void main(String[] args) {
        new B02();
        System.out.println(B02.a);
    }
}

class A02{
    static int a = 0;
    static {
        a = 1;
    }
}

class B02 extends A02{
    static {
        a = 2;
    }
}

分析步骤:
1、调用new创建对象,需要初始化B02,优先初始化父类。
2、执行A02的初始化代码,将a赋值为1。
3、B02初始化,将a赋值为2。

变化
将new B02();注释掉会怎么样?
分析步骤:
1、访问父类的静态变量,只初始化父类。
2、执行A02的初始化代码,将a赋值为1。

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

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

相关文章

Halcon 3D算子总结整理

halcon 3D包含以下几个模块: 3D Matching(3D匹配)3D Object Model(3D模型)3D Reconstruction(3D重构)3D Transformations(3D转换) 1. 3D Matching 1.1 3D Box3D盒查找器…

【Memcached】springBoot 集成 memcached 两万字长文带你认识memcached

目录 一、 memcached 介绍1.1 简介1.2 特性1.3 优点1.4 缺点1.5 实现原理1.6 适用场景1.7 不适用场景1.8 与 Redis 比较相同点1.9 与 Redis 比较不同点 二、对 java 的支持2.1 Memcached-java-client 客户端2.2 Spymemcached 客户端2.3 XMemcached 客户端 三、下载安装3.1 wind…

anaconda迁移深度学习虚拟环境 在云服务器上配置

1 anaconda 虚拟环境操作 1、 查看虚拟环境 conda info -e2、 创建新的虚拟环境 conda create -n deeplearning_all pip python3.63、 激活新建的虚拟环境 Conda activate deeplearning_all2 环境中相关库的版本即安装说明(这些库都是对应匹配的) …

1236 - 二分查找

代码 #include<bits/stdc.h> using namespace std; int a[1100000]; int main() {int n,x,l,r,p,mid,i;cin>>n;for(i1;i<n;i)cin>>a[i];cin>>x;l1;rn;p-1;while(l<r){mid(rl)/2;if(a[mid]x){pmid;break;}else if(x<a[mid]) rmid-1;else if(x…

微服务day04(上)-- RabbitMQ学习与入门

1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;需要实时响应。 异步通讯&#xff1a;就像发邮件&#xff0c;不需要马上回复。 两种方式各有优劣&#xff0c;打电话可以立即得到响应&#xff0c;但…

MySQL数据库 - 索引

一. 索引的相关知识 1. 索引的概念 是一个排序的列表&#xff0c;存储着索引值和这个值所对应的物理地址&#xff08;类似于C语言的链表通过指针指向数据记录的内存地址&#xff09;使用索引后可以不用扫描全表来定位某行的数据&#xff0c;而是先通过索引表找到该行数据对应…

NodeJS 集群模块: 为App创建集群实例

NodeJS 集群模块: 为App创建集群实例 目录 NodeJS 集群模块: 为App创建集群实例Node.js 集群介绍:终极扩展策略使用集群模块开始扩展 Node.js扩展 Node.js 的两种集群策略使用集群受益的 Node.js 应用程序示例没有集群的 Node.js:不可伸缩的原则集群操作:一个扩展的 Node.js…

全新体验|德克萨斯州奥斯汀市登陆 The Sandbox

以前所未有的方式探索德克萨斯州奥斯汀——The Sandbox迎来虚拟旅游&#xff0c;新体验由Smobler工作室打造。 我们的使命是为虚拟旅游创造新机遇&#xff0c;让每个人都能更方便地游览城市和国家。我们非常兴奋地宣布&#xff1a;Cobbleland&#xff1a;Austin&#xff0c;这款…

1.C#对接微信Native支付(准备工作)

近期有需求需要在PC网站接入微信支付&#xff0c;遂了解了一下相关文档。https://pay.weixin.qq.com/static/applyment_guide/applyment_index.shtml 官网文档种有多种支付对接方式比如&#xff1a;jsapi、native、app支付、小程序支付等。大家可自行了解&#xff0c;根据自身…

电子合同和纸质合同有同等法律效力吗?

根据《中华人民共和国民法典》的规定&#xff0c;电子合同是合同的一种形式&#xff0c;只要依法成立&#xff0c;就具有法律效力&#xff0c;和纸质合同具有同样的法律效力。同时&#xff0c;法律也认可了以电子数据交换、电子邮件等方式能够有形地表现所载内容&#xff0c;并…

深度解析:普通人运用ChatGPT10大经典场景,你用过几种?(内含使用教程)

本内容来源---布博士&#xff08;擎创产品专家&#xff09;公众号 很长时间没有更新ChatGPT相关内容了&#xff0c;最近一段时间一直在通过各种渠道了解大型语言模型&#xff0c;重点关注其在各个应用领域的使用情况&#xff0c;以此来了解其应用的边界。 在近两个月的学习过…

Emotion Prompt-LLM能够理解并能通过情感刺激得以增强

Large Language Models Understand and Can be Enhanced by Emotional Stimuli 情感智能对我们的日常行为和互动产生了显著的影响。尽管大型语言模型&#xff08;LLMs&#xff09;被视为向人工通用智能迈进的一大步&#xff0c;在许多任务中表现出色&#xff0c;但目前尚不清楚…

xercesc库中文保存XML功能实现

目录 一 参考链接 二 运行结果 三 代码 一 参考链接 DOM Programming Guide (apache.org) Xerces-c DOM XML文件的构造_xerces-c domimplementation-CSDN博客 Xerces-c库的使用-CSDN博客 二 运行结果 三 代码 #include "XercesC_Test.h"#if 1//参考链接&…

基于爬虫对山西省人口采集+机器学习的可视化平台

文章目录 数据来源一、研究背景与意义二、研究目标三、研究内容与方法四、预期成果五、代码讲解六、全文总结 数据来源 1.所有原数据均来自&#xff1a;国家统计局-政府的数据网站 2.涉及到的一些预测数据是根据现有数据进行预测而来。 本文从数据来源&#xff0c;研究意义&am…

ideaSSM博物馆网站系统VS开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 idea 开发 SSM 博物馆网站系统是一套完善的信息管理系统&#xff0c;结合SSM框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c…

基于单片机的实时水质监测系统设计

摘要:传统的水质监测存在人工成本高,取样时间长等诸多问题。为了解决这些问题,本文设计了一款基于单片机的实时水质监测系统,通过传感器采集到的数据,单片机通过zigbee 収送至云端,结合上位机软件可以实现实时的信息采集处理,实现了高敁、智能的水质监测工作。 兲键词:…

JavaMySQL高级一(下)

目录 1.常用函数 1.字符串函数 2.时间日期函数 3.聚合函数 4.数学函数 2.分布查询 3.子查询基础 1.简单子查询 1.常用函数 在程序开发过程中&#xff0c;除了简单的数据查询&#xff0c;还有基于已数据进行数据的统计分析计算等需求。因此&#xff0c;在SQL中将一…

【原创】三十分钟实时数据可视化网站前后端教程 Scrapy + Django + React 保姆级教程向

这个本来是想做视频的&#xff0c;所以是以讲稿的形式写的。最后没做视频&#xff0c;但是觉得这篇文还是值得记录一下。真的要多记录&#xff0c;不然一些不常用的东西即使做过几个月又有点陌生了。 文章目录 爬虫 SCRAPYxpath 后端 DJANGO前端 REACT Hello大家好这里是小鱼&a…

企业用大模型如何更具「效价比」?百度智能云发布5款大模型新品

服务8万企业用户&#xff0c;累计帮助用户精调1.3万个大模型&#xff0c;帮助用户开发出16万个大模型应用&#xff0c;自2023年12月以来百度智能云千帆大模型平台API日调用量环比增长97%...从一年前国内大模型平台的“开路先锋”到如今的大模型“超级工厂”&#xff0c;百度智能…

【MySQL | 第五篇】MySQL事务总结

文章目录 5.MySQL事务5.1什么是事务&#xff1f;5.2什么是数据库事务&#xff1f;5.3数据库事务四大特性5.4并发事务带来的问题及解决方案&#xff1f;5.4.1脏读/不可重复读/幻读5.4.2不可重复读和幻读有什么区别&#xff1f;5.4.3解决并发事务带来的问题&#xff08;1&#xf…