【Java八股面试系列】JVM-类和对象加载过程

目录

类和对象的加载过程

类的生命周期

类的加载过程

加载

验证

准备

解析

初始化

类卸载

对象的加载过程


类和对象的加载过程

什么是类加载和对象加载?

  1. 类加载(Class Loading):这是指JVM在运行时将类的字节码文件加载到内存中的过程。类加载的主要任务是找到类的字节码文件,然后读取它并存储在方法区中。这个过程是由类加载器完成的。

  2. 对象加载(Object Loading):这是对象在堆内存中分配空间的过程。当我们在代码中创建一个类的实例时,JVM会在堆内存中为这个对象分配空间,并将其实例化。这个过程是在类加载之后发生的。

简单来说,类加载是将类的字节码文件加载到内存中(Jvm虚拟机的方法区中),而对象加载是为这个类的实例在堆内存中分配空间并初始化。

类的生命周期

类从被加载到虚拟机内存中开始到卸载出内存为止,它的整个生命周期可以简单概括为 7 个阶段::加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)。其中,验证、准备和解析这三个阶段可以统称为连接(Linking)。

这 7 个阶段的顺序如下图所示:

一个类的完整生命周期

类的加载过程

Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚拟机是如何加载这些 Class 文件呢?

系统加载 Class 类型的文件主要三步:加载->连接->初始化。连接过程又可分为三步:验证->准备->解析

加载

主要目的就是使用二进制字节流将class文件加载进Jvm的方法区

类加载过程的第一步,主要完成下面 3 件事情:

  1. 通过全类名获取定义此类的二进制字节流。

  2. 将字节流所代表的静态存储结构转换为方法区的运行时数据结构。

  3. 在内存中生成一个代表该类的 Class 对象,作为方法区这些数据的访问入口。

加载这一步主要是通过我们后面要讲到的 类加载器 完成的。类加载器有很多种,当我们想要加载一个类的时候,具体是哪个类加载器加载由 双亲委派模型 决定(不过,我们也能打破由双亲委派模型)。

验证

验证是连接阶段的第一步,这一阶段的目的是确保 Class 文件的字节流中包含的信息符合《Java 虚拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。

验证的阶段因为比较关键,保证了后面的运行安全。这个阶段是比较耗费资源的,但是这个验证也是可以自己手动进行关闭的。如果我们的代码都是自己编写,并且引用的代码依赖都是自己使用过多次的,在生产环境的实施阶段就可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施,以缩短虚拟机类加载的时间。

验证阶段主要由四个检验阶段组成:

  1. 文件格式验证(Class 文件格式检查):基于二进制字节流进行实现,确保数据能够安全的加载到方法区之内。

  2. 元数据验证(字节码语义检查)

  3. 字节码验证(程序语义检查)

  4. 符号引用验证(类的正确性检查)

准备

准备阶段是正式为类变量(静态变量)分配内存并设置类变量初始值的阶段,这些内存都将在方法区中分配。对于该阶段有以下几点需要注意:

  1. 这时候进行初始化的都只是类变量,而不是实例变量。实例变量在对象进行初始化的时候都会被分配在堆中

  2. HotSpot 已经把原本放在永久代的字符串常量池、静态变量等移动到堆中,这个时候类变量则会随着 Class 对象一起存放在 Java 堆中。

  3. 这个阶段设置的初始值只是每个类型的默认值,比如 static int a = 11;这个时候初始化了的a的值为0,而不是11。但是如果是final关键字修饰的变量,则直接会被赋值为设置的值。

解析

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。 解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用限定符 7 类符号引用进行。

  • 虚拟机在类加载的解析阶段,会遍历类的常量池,查找所有的符号引用。

  • 对于每一个符号引用,虚拟机会尝试找到它引用的目标类、方法或字段。这可能需要加载其他的类或接口。

  • 如果找到了目标,虚拟机就会将这个符号引用替换为一个直接引用,这个直接引用可以直接访问目标类、方法或字段。

  • 如果找不到目标,或者目标不是一个有效的类、方法或字段(例如,尝试访问一个不存在的类或方法),那么解析过程就会失败,并且会抛出一个异常。

初始化

初始化阶段是执行初始化方法 <clinit> ()方法的过程,是类加载的最后一步,这一步 JVM 才开始真正执行类中定义的 Java 程序代码(字节码)。

说明:<clinit> ()方法是编译之后自动生成的。

对于初始化阶段,虚拟机严格规范了有且只有 6 种情况下,必须对类进行初始化(只有主动去使用类才会初始化类):

  1. 当遇到 new、 getstatic、putstatic 或 invokestatic 这 4 条字节码指令时,比如 new 一个类,读取一个静态字段(未被 final 修饰)、或调用一个类的静态方法时。

    • 当 jvm 执行 new 指令时会初始化类。即当程序创建一个类的实例对象。

    • 当 jvm 执行 getstatic 指令时会初始化类。即程序访问类的静态变量(不是静态常量,常量会被加载到运行时常量池)。

    • 当 jvm 执行 putstatic 指令时会初始化类。即程序给类的静态变量赋值。

    • 当 jvm 执行 invokestatic 指令时会初始化类。即程序调用类的静态方法。

  2. 使用 java.lang.reflect 包的方法对类进行反射调用时如 Class.forname("..."), newInstance() 等等。如果类没初始化,需要触发其初始化。

  3. 初始化一个类,如果其父类还未初始化,则先触发该父类的初始化。

  4. 当虚拟机启动时,用户需要定义一个要执行的主类 (包含 main 方法的那个类),虚拟机会先初始化这个类。

  5. MethodHandleVarHandle 可以看作是轻量级的反射调用机制,而要想使用这 2 个调用 就必须先使用 findStaticVarHandle 来初始化要调用的类。

类卸载

卸载类即该类的 Class 对象被 GC。

卸载类需要满足 3 个要求:

  1. 该类的所有的实例对象都已被 GC,也就是说堆不存在该类的实例对象。

  2. 该类没有在其他任何地方被引用

  3. 该类的类加载器的实例已被 GC

所以,在 JVM 生命周期内,由 jvm 自带的类加载器加载的类是不会被卸载的。但是由我们自定义的类加载器加载的类是可能被卸载的。

只要想通一点就好了,JDK 自带的 BootstrapClassLoader, ExtClassLoader, AppClassLoader 负责加载 JDK 提供的类,所以它们(类加载器的实例)肯定不会被回收。而我们自定义的类加载器的实例是可以被回收的,所以使用我们自定义加载器加载的类是可以被卸载掉的。

对象的加载过程

Java 对象的创建过程——五步

  1. 检查类是否已经被加载

    new关键字时创建对象时,首先会去运行时常量池中查找该引用所指向的类有没有被虚拟机加载,如果没有被加载,那么会进行类的加载过程。(加载将class文件读取到内存中,使用加载器进行加载)

  2. 为对象分配内存空间

    当类加载检查通过后,虚拟机会为新生对象分配内存空间,对象所需内存空间的大小在类加载完成后就已经确定了。为新生对象分配内存空间其实就是在Java堆中划分出一块确定大小的内存分配给新生对象。分配内存的方式有“指针碰撞”和“空闲列表”两种,选择哪种分配方式取决于Java堆内存是否规整。

    内存分配的两种方式

    • 指针碰撞 使用场合:堆内存规整(即没有内存碎片)的情况下。 实现原理:将用过的内存都整合到一边,没有用过的内存放到另一边,中间有一个分界指针,当需要为新对象分配内存空间时,只需要将分界指针向没有用过的内存一侧移动对象内存大小位置即可。

    • 空闲列表 使用场合:堆内存不规整的情况下。(JDK8默认的GR垃圾回收方式,是不规整的方式) 实现原理:虚拟机会维护一个列表,该列表记录了哪些内存是可用的,当需要为新对象分配内存空间时,只需要在列表中找一块足够大小的内存分配给对象实例,然后更新列表记录。 选择以上两种方式中的哪一种,取决于 Java 堆内存是否规整。而 Java 堆内存是否规整,取决于 GC 收集器垃圾采用的垃圾收集算法

  3. 对象初始化零值

    内存分配完成后,虚拟机需要将新分配的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段可以在Java代码中可以不赋初始值就直接使用,程序能够访问这些实例字段的数据类型所对应的零值。

  4. 设置对象头

    初始化零值之后,虚拟机需要对对象头进行必要的设置,例如这个对象是哪个类的实例,如何才能找到这个类的元数据信息,对象的哈希码、GC 分代年龄、锁标志位、偏向锁标志位、线程持有的锁信息、对象是否可用等信息会存放到对象头中。另外,根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。

  5. 执行init方法

    执行完new指令后会接着执行init方法,将对象按照程序员的需求来进行初始化,这样一个真正可用的对象才算完全产生出来。

上述为无父类的对象创建过程。对于有父类的对象创建过程,还需满足如下条件:

  1. 先加载父类;再加载本类;

  2. 先执行父类的实例的初始化方法init(成员变量、构造代码块),父类的构造方法;执行本类的实例的初始化方法init(成员变量、构造代码块),本类的构造方法。

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

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

相关文章

Java实现新能源电池回收系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户档案模块2.2 电池品类模块2.3 回收机构模块2.4 电池订单模块2.5 客服咨询模块 三、系统设计3.1 用例设计3.2 业务流程设计3.3 E-R 图设计 四、系统展示五、核心代码5.1 增改电池类型5.2 查询电池品类5.3 查询电池回…

php 函数(方法)、日期函数

php 函数、日期函数 1. php函数2. 日期函数 1. php函数 <?php// 创建一个函数 function hello($who) {echo $who.Hello World!; }hello("老张");给参数一个默认值&#xff0c;当然自己有变量走自己的 2. 日期函数 <?php/** date(Y-m-d H:i:s)返回的时间是…

恒流模块与常用电容

户外电源电芯&#xff1a;DJ采用无热中心设计&#xff1a;每个电芯都有一部分裸露在外面&#xff0c;保证良好散热上 固态电容相较于普通电解电容具有更高的电气性能、更长的使用寿命和更稳定的温度特性&#xff0c;但成本也相对较高。固态电容在1块左右&#xff0c;电解电容在…

Midjourney绘图欣赏系列(六)

Midjourney介绍 Midjourney 是生成式人工智能的一个很好的例子&#xff0c;它根据文本提示创建图像。它与 Dall-E 和 Stable Diffusion 一起成为最流行的 AI 艺术创作工具之一。与竞争对手不同&#xff0c;Midjourney 是自筹资金且闭源的&#xff0c;因此确切了解其幕后内容尚不…

中国半导体设备行业概述

TrendForce根据各种行业数据和主要代表性公司的最新财务报告综合分析指出&#xff0c;中国本土设备产业在半导体制造流程&#xff08;除光刻机外&#xff09;的各个阶段均有覆盖能力。具体来说&#xff0c;国产设备在中国本地市场中&#xff0c;在剥离、清洗及蚀刻等工艺上的本…

二、ActiveMQ安装

ActiveMQ安装 一、相关环境二、安装Java8三、下载安装包四、启动五、其他命令六、开放端口七、后台管理 一、相关环境 环境&#xff1a;Centos7.9安装ActiveMQ版本&#xff1a;5.15.9JDK8 二、安装Java8 安装教程&#xff1a;https://qingsi.blog.csdn.net/article/details/…

.NET Core WebAPI中使用swagger版本控制,添加注释

一、效果 二、实现步骤 在代码中添加注释 在项目属性中生成API文档 在Program中注册Swagger服务并配置文档信息 // 添加swagger注释 builder.Services.AddSwaggerGen(x > {x.SwaggerDoc("v1", new OpenApiInfo { Title "Swagger标题", Version "…

MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(2)-Swagger框架集成

Swagger是什么&#xff1f; Swagger是一个规范且完整API文档管理框架&#xff0c;可以用于生成、描述和调用可视化的RESTful风格的 Web 服务。Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口&#xff0c;可以让人和计算机拥有无须访问源码、文档或网络流量监测就…

前端秘法进阶篇----这还是我们熟悉的浏览器吗?(浏览器的渲染原理)

目录 一.浏览器渲染原理 二.渲染时间点 三.渲染流水线 1.解析html(Parse HTML) 1.1解析成DOM树(document object model) 1.2解析成CSSOM树(css object model) 2.样式计算(Recalculate Style) 3.布局(Layout) 4.分层(Layer) 5. 绘制(Paint) 6.分块(Tiling) 7. 光栅化…

360可视门铃双摄版恢复案例

家用的智能摄像头恢复了很多&#xff0c;但是可视门铃的恢复却是第一次&#xff0c;现代社会似乎已经全方位处于监控网络之下。360的产品很多&#xff0c;可视门铃只是其众多品牌中的一个&#xff0c;这个案例能让我们窥视到360的开发小精产品的理念。 故障存储: 64G TF卡/ex…

时序预测 | Matlab实现BO-LSSVM贝叶斯算法优化最小二乘支持向量机时间序列预测

时序预测 | Matlab实现BO-LSSVM贝叶斯算法优化最小二乘支持向量机时间序列预测 目录 时序预测 | Matlab实现BO-LSSVM贝叶斯算法优化最小二乘支持向量机时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab实现BO-LSSVM贝叶斯算法优化最小二乘支持向量机时间…

函数、极限、连续——刷题(5

目录 1.题目&#xff1a;2.解题思路和步骤&#xff1a;3.总结&#xff1a;小结&#xff1a; 1.题目&#xff1a; 2.解题思路和步骤&#xff1a; 首先可能想到的是答案为0&#xff0c;但是不可以把 直接化简为n 这里要用到分子分母的平方差&#xff0c;sin^2的周期为π&#x…

计算机网络——14CDN

CDN 视频流化服务和CDN&#xff1a;上下文 视频流量&#xff1a;占据着互连网大部分的带宽 Netflix&#xff0c;YouTube&#xff1a;占据37%&#xff0c;16%的下行流量 挑战&#xff1a;规模性-如何服务~1B用户&#xff1f; 单个超级服务器无法提供服务&#xff08;为什么&am…

函数、极限、连续——刷题(4

目录 1.题目&#xff1a;2.解题思路和步骤&#xff1a;3.总结&#xff1a;小结&#xff1a; 1.题目&#xff1a; 2.解题思路和步骤&#xff1a; 记住这个公式即可&#xff1a; 所以就很容易求解了&#xff1a; 3.总结&#xff1a; 记住这个公式即可&#xff1a; 小结&am…

祝所有的CSDN社区成员们新年快乐

文章目录 尊敬的CSDN社区成员们&#xff0c; 在新年的钟声即将敲响之际&#xff0c;我携带着满心祝福与期许&#xff0c;以字为舟&#xff0c;穿越虚拟与现实的界限&#xff0c;来到您的身边&#xff0c;向每一位热爱编程、投身技术研究、在CSDN平台上挥洒智慧和汗水的朋友们&a…

如何使用iptables或者firewalld配置Linux系统的防火墙策略

在网络安全中&#xff0c;防火墙是一种关键的安全设备&#xff0c;用于保护计算机网络免受恶意攻击和未经授权的访问。在Linux系统中&#xff0c;我们可以使用iptables或者firewalld来配置防火墙策略。本文将介绍如何使用这两种工具来配置Linux系统的防火墙策略&#xff0c;包括…

数据结构:4_二叉树

二叉树 一.树概念及结构 1. 树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 有一个**特殊的…

17.3.1.6 自定义处理

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 模拟某款图像处理软件的处理&#xff0c;它只留下红色、绿色或者蓝色这样的单一颜色。 首先按照颜色划分了6个色系&#xff0c;分别…

基于Arduino UNO设计一个温控制系统

目录 概述 1 硬件结构 1.1 整体硬件介绍 1.2 硬件连接结构 2 软件设计 2.1 软件功能介绍 2.2 关于Arduino的一些知识点 2.2.1 定时器 2.2.2 PWM 2.3 代码实现 2.3.1 编译工具 2.3.2 详细代码 3 测试 3.1 温度数据监控 3.2 温控测试 概述 本文介绍如何使用Ardui…

Rust 语言学习杂谈 (end) (各种工作中遇到的疑难杂症)

1.在运行 “cargo build --release” 的时候&#xff0c;到底发生了什么&#xff1f; 源 (GPT4.0) : 当我们运行 cargo build --release 命令时&#xff0c;实际上在进行一系列复杂的步骤来编译和构建 Rust 项目的发布版本。这个过程大致可以分解为以下几个步骤&#xff1a;…