03. 对象的创建,存储和访问原理
文章目录
- 01. 对象创建
- 1.1 创建过程概览
- 1.2 类加载检查
- 1.3 为对象分配内存
- 1.4 将内存空间初始化为零值
- 1.5 设置对象的必要信息
- 1.6 总结
- 02. 对象的内存布局
- 2.1 对象头区域
- 2.2 实例数据区域
- 2.3 对齐填充区域
- 2.4 总结
- 03. 对象的访问定位
- 其他介绍
- 01.关于我的博客
注:读者在阅读博客的过程中总结各个文章的知识,写了很多笔记。但是本文原作者的写作和总结已经很翔实了,因此本文绝大多数照搬原作者的写作,中间稍加自己的理解和修改。原文来源如下:
作者:Carson带你学Android
链接:https://juejin.cn/post/6844903681553334285
01. 对象创建
- 在开发使用时,创建
Java对象仅仅只是是通过关键字new:A a = new A();,可是它真的这么简单吗?我想不是的,他是一个很复杂的过程。
1.1 创建过程概览
-
对象创建的流程概览如下:
- new指令启动流程。
- 类加载检查
- 为对象分配内存
- 将内存空间初始化为零值
- 对对象进行必要的设置
-
下面我将对每个步骤进行讲解。

1.2 类加载检查
- 我们,调用new的时候,知道new指令右侧是有一个参数的, 它是一个符号引用,我们要检查是否能在 常量池中 定位到该符号引用,未定位到,则说明类尚未加载,我们要进行类的加载机制。这个我们可以后续介绍。
如果没有,需要先执行相应的类加载过程
1.3 为对象分配内存
-
现在我们类加载检查通过了,确定类已经被加载进来了。
-
虚拟机将会在堆中为对象分配内存,即把一块确定大小的内存从
Java堆中划分出来,对象所需内存的大小在类加载完成后便可完全确定。 -
内存分配 根据 Java堆内存是否绝对规整 分为两种方式:指针碰撞 & 空闲列表
怎么理解这里的规整和不规整?
Java堆内存 规整:已使用的内存在一边,未使用内存在另一边Java堆内存 不规整:已使用的内存和未使用内存相互交错

-
指针碰撞:已使用内存在一边,未使用内存在另一边,中间有一个指针作为分界指示器,那么,分配对象内存 = 把指针向 未使用内存 移动一段 与对象大小相等的距离
-
-
空闲列表:虚拟机维护着一个 记录可用内存块 的列表,在分配时从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录
那么Java堆为什么有时候规整,有时候不规整?
Java堆是否规整 由所采用的垃圾收集器是否带有压缩整理功能决定。因此:
- 使用带
复制和标记-整理算法的垃圾收集器时(如Serial、ParNew垃圾收集器),采用指针碰撞; - 使用
标记-清除算法的垃圾收集器时(如CMS垃圾收集器),采用空闲列表。
-
可是对象在堆中分配是非常频繁的操作,而堆又是进程共享的,会存在并发情况下线程安全的问题。如,正在给对象A分配内存,指针还没有来得及修改,对象B又同时使用了原来的指针来分配内存。我们怎么解决这个问题呢?
- 加锁?ok,这可以,这是最基础的解决方式。但是,效率较低,有没有其它更好的方式呢?有的,孩子,我们可以采用更细的颗粒度的。
- 我们可以为每个线程在
Java堆中预先分配一小块内存(本地线程分配缓冲(Thread Local Allocation Buffer,TLAB)),哪个线程要分配内存,就在哪个线程的TLAB上分配,只有TLAB用完并分配新的TLAB时才需要同步锁。
1.4 将内存空间初始化为零值
- 内存分配完成后,虚拟机需要将分配到的内存空间初始化为零(不包括对象头),这保证了对象的实例字段在使用时可不赋初始值就直接使用(对应值 = 0)
1.5 设置对象的必要信息
-
如,设置 这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头中。
-
至此,从
Java虚拟机的角度来看,一个新的Java对象创建完毕。但从Java程序开发来说,对象创建才刚开始,需要进行一些初始化操作。
1.6 总结
- 下面用一张图总结
Java对象创建的过程
02. 对象的内存布局
-
那么在
Java对象创建后,到底是如何被存储在Java内存里的呢? -
对象在 Java内存中的 存储布局 可分为三块:
- 对象头 存储区域
- 实例数据 存储区域
- 对齐填充 存储区域
-

-
下面我会详细说明每一块区域。
2.1 对象头区域
此处存储的信息包括两部分:
- 对象自身的运行时数据(
Mark Word)
- 如哈希码(
HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等- 该部分数据被设计成1个 非固定的数据结构 以便在极小的空间存储尽量多的信息(会根据对象状态复用存储空间)
- 对象的类型指针
- 即对象指向它的类元数据的指针
- 虚拟机通过这个指针来确定这个对象是哪个类的实例
- 如果对象是数组,那么在对象头中还必须有一块用于记录数组长度的数据
因为虚拟机可以通过普通Java对象的元数据信息确定对象的大小,但是从数组的元数据中却无法确定数组的大小。
2.2 实例数据区域
- 存储对象的实例变量,这是对象真正有效的数据
2.3 对齐填充区域
- 存储的信息:占位符,起到占位作用,当对象的大小不是8字节的整数倍,就需要通过对齐填充来补全。
为什么要补全呢?这不是白白浪费空间吗?
这涉及到底层的原理:
在程序员看来,内存是由一个个的字节组成。而CPU并不是这么看待的,CPU把内存当成是一块一块的,这里cpu的块是8字节大小。
假如有一个8字节大小的数据,它分为两种情况:
1、数据从0字节开始
2、数据从1字节开始
- 当该数据是从0字节开始时,很CPU只需读取内存一次即可把这8字节的数据完全读取到寄存器中。
- 当该数据是从1字节开始时,问题变的有些复杂,此时该数据不是位于内存读取边界上,这就是一类内存未对齐的数据。此时CPU先访问一次内存,读取0—7的数据进寄存器,并再次读取8—15的数据进寄存器,接着把0和9后续的的数据剔除,最后合并1- 9这8字节的数据进寄存器。对一个内存未对齐的数据进行了这么多额外的操作,大大降低了CPU性能。因此我们采用补全,损失一些空间,换取更高的执行效率?
2.4 总结

**
03. 对象的访问定位
- 问:建立对象后,该如何访问对象呢?
实际上需访问的是 对象类型数据 & 对象实例数据
- 答:
Java程序 通过 栈上的引用类型数据(reference) 来访问Java堆上的对象
由于引用类型数据(reference)在 Java虚拟机中只规定了一个指向对象的引用,但没定义该引用应该通过何种方式去定位、访问堆中的对象的具体位置
所以对象访问方式取决于虚拟机实现。目前主流的对象访问方式有两种:
- 句柄 访问
- 直接指针 访问
具体请看如下介绍:很有意思。

其他介绍
01.关于我的博客
-
csdn:http://my.csdn.net/qq_35829566
-
掘金:https://juejin.im/user/499639464759898
-
github:https://github.com/jjjjjjava
-
简书:http://www.jianshu.com/u/92a2412be53e
-
邮箱:[934137388@qq.com]
相关文章:
03. 对象的创建,存储和访问原理
文章目录 01. 对象创建1.1 创建过程概览1.2 类加载检查1.3 为对象分配内存1.4 将内存空间初始化为零值1.5 设置对象的必要信息1.6 总结 02. 对象的内存布局2.1 对象头区域2.2 实例数据区域2.3 对齐填充区域2.4 总结 03. 对象的访问定位其他介绍01.关于我的博客 注:读…...
机器学习-GBDT算法
目录 一. GBDT 核心思想 二. GBDT 工作原理 **(1) 损失函数优化** **(2) 负梯度拟合** **(3) 模型更新** 三. GBDT 的关键步骤 四. GBDT 的核心优势 **(1) 高精度与鲁棒性** **(2) 处理缺失值** **(3) 特征重要性分析** 五. GBDT 的缺点 **(1) 训练…...
redis基础结构
title: redis基础结构 date: 2025-03-04 08:39:12 tags: redis categories: redis笔记 Redis入门 (NoSQL, Not Only SQL) 非关系型数据库 关系型数据库:以 表格 的形式存在,以 行和列 的形式存取数据,一系列的行和列被…...
【keil】一种将STM32的armcc例程转换为armclang的方式
【keil】一种将所有armcc例程转换为armclang的方式 改的原因第一步下载最新arm6第二步编译成功 第三步去除一些warning编译成功 我这边用armclang去编译的话,主要是freertos中的portmacro.h和port.c会报错 改的原因 我真的服了,现在大部分的单片机例程都…...
计算机视觉算法实战——表面缺陷检测(表面缺陷检测)
✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ 1. 引言 表面缺陷检测是计算机视觉领域中的一个重要研究方向,旨在通过图像处理和机器学习技术自动检测产品表面的缺陷&…...
window下的docker内使用gpu
Windows 上使用 Docker GPU需要进行一系列的配置和步骤。这是因为 Docker 在 Windows 上的运行环境与 Linux 有所不同,需要借助 WSL 2(Windows Subsystem for Linux 2)和 NVIDIA Container Toolkit 来实现 GPU 的支持。以下是详细的流程: 一、环境准备 1.系统要求 Window…...
Modbus协议(TCP)
从今开始,会详细且陆续整理各类的通信协议,以便在需要且自身忘记的情况下,迅速复习。如有错误之处,还请批评指正。 一、Modbus协议的简述 Modbus协议作为应用层协议,基于主从设备模型,主设备负责请求消息&…...
虚拟系统配置实验报告
一、实验拓扑图 二、实验配置 要求一: 虚拟系统: 设置管理: 进行信息配置 R1配置 虚拟系统配置 a: b: c: 测试 a–>b: 检测...
Agentic系统:负载均衡与Redis缓存优化
摘要 本文在前文Agentic系统的基础上,新增负载均衡(动态调整线程数以避免API限流)和缓存机制(使用Redis存储搜索结果,减少API调用)。通过这些优化,系统在高并发场景下更加稳定高效。代码完整可…...
28-文本左右对齐
给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。 你应该使用 “贪心算法” 来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可…...
建筑兔零基础自学python记录39|实战词云可视化项目——章节分布10(上)
这次我们来制作《红楼梦》各章节的分布情况: 源代码: import pandas as pd import numpy as np import matplotlib.pyplot as pltdf_hlm pd.read_csv("hlm.txt", names["hlm_texts"]).dropna()df_hlm df_hlm[~df_hlm.hlm_texts.s…...
Impacket工具中的横向渗透利器及其使用场景对比详解
在渗透测试中,横向移动(Lateral Movement)是指攻击者在获得一个系统的控制权限后,通过网络进一步渗透到其他系统的过程。Impacket 是一款强大的渗透测试工具集,提供了多种实现横向渗透的脚本,常见的工具包括…...
基于java,SpringBoot和Vue的医院药房药品管理系统设计
摘要 随着医疗行业信息化的快速发展,高效、精准的医院药房药品管理对于提升医疗服务质量和医院运营效率至关重要。本文基于 Java 语言,采用 SpringBoot 框架和 Vue 框架进行医院药房药品管理系统的设计与研究。该系统以 SpringBoot 作为后端开发框架&am…...
MQ保证消息的顺序性
在消息队列(MQ)中保证消息的顺序性是一个常见的需求,尤其是在需要严格按顺序处理业务逻辑的场景(例如:订单创建 → 支付 → 发货)。 一、消息顺序性被破坏的原因 生产者异步/并行发送:消息可能…...
cmake、CMakeLists.txt、make、ninja
文章目录 一、概念0.cmake官网1.什么是cmake2.为什么使用cmake3.CMakeLists.txt 二、CMakeLists.txt语法:如何编写CMakeLists.txt,语法详解(0)语法基本原则(1)project关键字(2)set关键字(3)message关键字(4)add_executable关键字(5)add_subdirectory关键…...
数据结构与算法 计算机组成 八股
文章目录 数据结构与算法数组与链表的区别堆的操作红黑树定义及其原理 计算机组成int和uint的表示原码反码补码移码的定义?为什么用补码? 数据结构与算法 数组与链表的区别 堆的操作 红黑树定义及其原理 计算机组成 int和uint的表示 原码反码补码移…...
RoboBrain:从抽象到具体的机器人操作统一大脑模型
25年2月来自北大、北京智源、中科院自动化所等的论文“RoboBrain: A Unified Brain Model for Robotic Manipulation from Abstract to Concrete”。 目前的多模态大语言模型(MLLM) 缺少三项必备的机器人大脑能力:规划能力,将复杂…...
算法 之 前缀和 与 滑动窗口 与 背包问题 的差异(子数组之和为k问题)
文章目录 使用前缀和哈希表560.和为K的子数组525.连续数组2588.统计美丽子数组数目 子数组的定义是原来的数组当中连续的非空的序列,而我们的背包问题的选与不选的情况,对应的是这个非连续的情况,那么这种情况就要注意当然啦,对于线性的时间内…...
微电网协调控制器ACCU-100 分布式光伏 光储充一本化
安科瑞 华楠 18706163979 应用范围: 分布式光伏、微型风力发电、工商业储能、光储充一体化电站、微电网等领域。 主要功能: 数据采集:支持串口、以太网等多通道实时运行,满足各类风电与光伏逆变器、储能等 设备接入ÿ…...
IDEA入门及常用快捷键
IDEA是java常用的IDE。当run一个.java文件时,其实是经历了先编译为.class,再运行的过程。 在project文件夹中,out文件夹存储编译的.class文件,src文件夹存储.java代码文件。 设置自动导包 快捷键: 格式化快捷键&…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...


