JVM系列(六) -对象的创建过程

一、摘要

在之前的文章中,我们介绍了类加载的过程和 JVM 内存布局相关的知识。本篇我们综合之前的知识,结合代码一起推演一下对象的真实创建过程,以及对象创建完成之后在 JVM 中是如何保存的。

二、对象的创建

在 Java 中,创建对象的方式有很多种,比如最常见的通过new xxx()来创建一个对象,通过反射Class.forName(xxx).newInstance()来创建对象等。其实无论是哪种创建方式,JVM 底层的执行过程是一样的。

对象的创建过程,可以用如下图来简要概括。

创建对象大致分为 5 个步骤:

  • 1.检查类是否加载,如果没有就先执行类的加载
  • 2.分配内存
  • 3.初始化零值
  • 4.设置头对象
  • 5.执行初始化方法,例如构造方法等

下面我们一起来看下每个步骤具体的工作内容。

2.1、类加载检查

当需要创建一个类的实例对象时,比如通过new xxx()方式,虚拟机首先会去检查这个类是否在常量池中能定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化,如果没有,那么必须先执行类的加载流程;如果已经加载过了,会在堆区有一个类的 class 对象,方法区会有类的相关元数据信息。

为什么在对象创建时,需要有这一个检查判断?

主要原因在于:类的加载,通常都是懒加载,只有当使用类的时候才会加载,所以先要有这个判断流程

关于类的加载过程,在之前的文章中已经有所介绍,有兴趣的朋友可以翻看之前的文章。

2.2、分配内存

类加载成功后,虚拟机就能够确定对象的大小了,此时虚拟机会在堆内存中划分一块对象大小的内存空间出来,分配给新生对象。

虚拟机如何在堆中分配内存的呢?

主要有两种方式:

  • 1.指针碰撞法
  • 2.空闲列表法

下面我们一起来看看相关的内存分配方式。

2.2.1、指针碰撞法

如果内存是规整的,那么虚拟机将采用指针碰撞法来为对象分配内存。

指针碰撞法,简单的说就是所有用过的内存在一边,空闲的内存在另一边,中间放着一个指针作为分界点的指示器,分配内存时会把指针向空闲一方挪动一段,直到能容纳对象大小的位置。

如果垃圾收集器选择的是 Serial、ParNew 这种基于压缩算法的,虚拟机会采用这种分配方式。

2.2.2、空闲列表法

如果内存不是规整的,已使用的内存和未使用的内存相互交错,那么虚拟机将采用空闲列表法来为对象分配内存。

空闲列表法,简单的说就是在虚拟机内部维护了一个列表,会记录哪些内存块是可用的,在分配的时候会从列表中找到一块能容纳对象大小的空间,划分给对象实例,并更新列表上的内容。

如果垃圾收集器选择的是 CMS 这种基于标记-清除算法的,虚拟机会采用这种分配方式。

2.2.3、内存分配安全问题

我们知道,虚拟机是支持多个线程同时分配内存的,是否会有线程安全的问题呢?

答案是:肯定存在的。比如用指针碰撞法时,虚拟机正在给对象 A 分配内存,但指针还没来及修改,此时又有一个线程给对象 B 分配内存,同时使用了原来的指针来分配,最后的结果就是这个区域只分配来一个对象,另一个对象被覆盖了。

针对内存分配时存在的线程安全问题,虚拟机采用了两种方式来进行处理:

  • CAS+重试机制:通过 CAS 操作移动指针,只有一个线程可以移动成功,移动失败的线程重试,直到成功为止
  • TLAB (thread local Allocation buffer):也称为本地线程分配缓冲,这个处理方式思想很简单,就是当线程开启时,虚拟机会为每个线程分配一块较大的空间,然后线程内部创建对象的时候,就从自己的空间分配,这样就不会有并发问题了,当线程自己的空间用完了才会从堆中分配内存,之后会转为通过 CAS+重试机制来解决并发问题

以上就是虚拟机解决对象内存分配时存在的线程安全问题的措施。

2.3、初始化零值

初始化零值,顾名思义,就是对分配的这一块内存初始化零值,也就是给实例对象的成员变量赋于零值,比如 int 类型赋值为 0,引用类型为null等操作。这样对象就可以在没有赋值情况下使用了,只不过访问对象的成员变量都是零值。

2.4、设置头对象

初始化零值完成之后,虚拟机就会对对象进行必要的设置,比如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息,这些信息都会存放在对象头中。这部分数据,官方称它为“Mark Word”。

在 HotSpot 虚拟机中,对象在内存中存储的布局可以分为 3 块区域:对象头 (Header)、 实例数据 (Instance Data) 和对齐填充位 (Padding)。

以 32 位的虚拟机为例,对象的组成可以用如下图来简要概括。(64位的虚拟机略有不同)

各部分区域功能如下:

  • 对象头:分为 Mark Word 和元数据区,如果是数组对象,还有记录数组长度的区域。这三块保存着对象的 hashCode 值,锁的状态,类元数据指针,对象的分代年龄等等信息。
  • 实例数据:顾名思义,用于保存对象成员变量的值,如果变量是引用类型,保存的是内存地址
  • 对齐填充位:因为 HotSpot 虚拟机要求对象的起止地址必须是 8 字节的整数倍,也就是要求对象的大小为 8 字节的整数倍,如果不足 8 字节的整数倍,那么就需要通过对齐填充进行占位,补够 8 字节的

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

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

相关文章

Spring 循环依赖原理及解决方案

一、什么是循环依赖 循环依赖指的是一个实例或多个实例存在相互依赖的关系(类之间循环嵌套引用)。 举例: Component public class AService {// A中注入了BAutowiredprivate BService bService; }Component public class BService {// B中也…

Redis 的标准使用规范之数据类型使用规范

数据类型使用规范 提示:以下是本篇文章正文内容,可供参考 (1)、字符文本(STRING) 【建议】选型为简易文本类缓存 :比如普通的字符、文本、Json 结构 ,通常能起到加速读写和降低后端压力的作用。 【建议】…

数据库系统 第46节 数据库版本控制

数据库版本控制是确保数据库架构和数据模型随着时间的推移而正确演进的重要实践。它允许开发团队跟踪数据库的变更历史,回滚到以前的版本,以及在不同环境(如开发、测试和生产环境)之间同步数据库结构。以下是两种主要的数据库版本…

ActiveMQ 的网络连接及消息回流机制

1、ActiveMQ 的网络连接 activeMQ 如果要实现扩展性和高可用性的要求的话,就需要用用到网络连接模式。 NetworkConnector:主要用来配置 broker 与 broker 之间的通信连接 如上图所示,MQ 服务器1 和MQ 服务器2 通过 NewworkConnector 相连&…

Leetcode Hot 100刷题记录 -Day12(轮转数组)

轮转数组 问题描述: 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4]解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向…

一台笔记本电脑的硬件都有哪些以及对应的功能

一台笔记本电脑的硬件通常包括多个关键组件,这些组件共同协作,确保电脑的正常运行。以下是笔记本电脑的主要硬件及其功能: 1. 中央处理器(CPU) 功能:CPU 是电脑的“大脑”,负责处理所有的计算…

CocosCreator面试真题详解

最近有位同学面试Cocos Creator,我们把面试时问道的真题列举出来,并配上参考答案。 问题1: 你们公司项目时如何做战斗系统的? 面试官你好,做战斗系统和架构的时候,我们一般把代码逻辑分成3层来设计,同时把数据独立出…

Linux业务系统将/home目录删除并将空间扩给根目录

原有目录空间分配如下: [roothisdb ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/cl-root 21G 10G 11G 50% / devtmpfs 905M 0 905M 0% /dev tmpfs 920M 177M 744M 20% /dev/shm tm…

千益畅行,共享旅游卡,有哪些优势和特点?

1、同行人数灵活: 与一般旅游卡相比,千益畅行旅游卡对同行人数的限制更宽松,单卡支持 2 至 6 人同时出行,能满足小团体、家庭等多人出行需求,为多人共同出游提供了便利和优惠。 2、服务模式多样: 1&#xf…

前端月中总结

1、领导一拍脑门想要一个内部聊天软件 --基于open IM二次开发 背景 前段时间不是接手了一个内部办公软件的项目嘛,这个项目已经写了三四年了,一代代的前端融合了不知到多少种代码风格,再加上最初搭这个项目架子的人不知道咋想的&#xff0c…

操作系统 ---- 进程的概念、组成、特征

学习路线: 一、进程的概念及组成 我们通过一个例子来说明进程的概念以及程序和进程的区别。 我们在Windows操作系统中打开任务管理器,在任务管理器当中能看到此时系统当中运行的进程有哪些,如下图所示: 此时&#…

H5漂流瓶社交系统源码

一个非常有创意的H5漂流瓶社交系统源码,带完整前端h5和后台管理系统。 环境:Nginx 1.20.1-MySQL 5.6.50-PHP-7.3 代码下载

一家电子信息企业终止,前五大客户收入占比超九成,募资合理性存疑

兴天科技终止原因如下:首先,兴天科技前五大客户收入占比约超九成,客户集中度较高且高于行业平均水平,其中近期来自第一大客户收入占比超七成,单一客户依赖程度进一步上升;其次,兴天科技除第一大…

Spring boot启动过程详解

程序设计的所有原则和方法论都是追求一件事——简单——功能简单、依赖简单、修改简单、理解简单。因为只有简单才好用,简单才好维护。因此,不应该以评论艺术品的眼光来评价程序设计是否优秀,程序设计的艺术不在于有多复杂多深沉,…

ffmpeg的安装和使用教程及案例

FFmpeg的安装与使用教程 一、FFmpeg简介 FFmpeg是一个开源的、跨平台的音视频处理工具,可以用来转换、播放、录制、流化音视频数据,以及进行多种音视频编码和解码。 二、安装FFmpeg 1. Windows系统安装 下载预编译的二进制文件:从FFmpeg…

starrocks结合同步和异步物化视图建立数据湖和数据仓库

StarRocks 是一个高性能的开源 MPP(大规模并行处理)数据库,主要用于 OLAP(联机分析处理)场景。它支持各种数据操作,包括数据仓库中的大规模查询处理。同步和异步物化视图是 StarRocks 中的数据处理特性&…

云原生学习交流

欢迎加入技术交流群&#xff0c;与阿里、腾讯、字节、华为等运维大佬面对面交流和互相学习。 请扫码备注 加群&#xff0c;<城市>-<公司/自由职业>-<昵称>&#xff0c;如“加群&#xff0c;广州-阿里-行则”&#xff1a;

LabVIEW灵活集成与调试的方法

在LabVIEW开发中&#xff0c;为了构建一个既便于调试又能灵活集成到主VI中的控制VI&#xff0c;开发者需要采用适当的编程方式和架构。常见的选择包括模块化设计、状态机架构以及事件驱动编程。这些方法有助于简化调试过程、提高系统的稳定性&#xff0c;并确保代码的重用性和可…

目标检测-YOLOv4

YOLOv4介绍 YOLOv4 是 YOLO 系列的第四个版本&#xff0c;继承了 YOLOv3 的高效性&#xff0c;并通过大量优化和改进&#xff0c;在目标检测任务中实现了更高的精度和速度。相比 YOLOv3&#xff0c;YOLOv4 在框架设计、特征提取、训练策略等方面进行了全面升级。它在保持实时检…

分布式事务Seata原理及其项目使用

0.Seata官方文档 1.Seata概念及原理 Seata是什么 Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。 Seata主要由三个重要组…