Java对象在堆和栈上的存储(对象布局,待完善)

0、前言

这里提到的 Java 对象不仅仅包含引用类型(Object),还包含基本数据类型(boolean、int、long、float、double)。文中部分图片来源于 B站 黑马程序员。

1、在栈上的数据存储

1.1、局部变量

局部变量包含以下情况:

  • 方法中定义的变量
  • 方法的形参

注:在非 static 修饰的成员方法中,第一个形参是 this,代表当前类的实例对象

1.2、槽位(slot)

各种类型变量在堆空间和栈空间中的内存分配,常说的 int 占用 4B 是针对堆中变量,而在栈中是按照槽位(slot)进行分配的。

数据类型字节数(堆空间)槽位数(栈空间)
boolean1B1
char2B1
byte1B1
short2B1
int4B1
long8B2
float4B1
double8B2
Object见对象在堆上的数据存储中的相关讨论1

总结:

  • 1 slot = 机器字长(32 位机中 32 bit,64 位机中 64 bit)
  • longdouble 占用 2 个 slot
  • 其它类型占用 1 个 slot

1.3、堆数据和栈数据的赋值过程

一般情况而言,同类型变量在堆中的长度更短,在栈中的长度更长。总的转换思路为:

  • 堆 -> 栈:按符号位进行填充,负数在前面填充1,正数在前面填充0,能够保证在补码意义上值保持不变
  • 栈 -> 堆:截断 (boolean 类型比较特殊,只取最后 1bit,而不是 1B)

下面分别是 -5 和 5 的补码表示
在这里插入图片描述

复习点:给定一个负数,写出其补码

  1. 先写出其倒数(正数)的补码(即原码)
  2. 从右到左找到第一个1,左取反,右不变

1.4、测试案例

Java 代码

public class ObjectStackLayout {static class MyObject {String aString;Integer aInteger;int anInt;boolean aBoolean;double aDouble;}public static void main(String[] args) {boolean b = true;char ch = 'a';short sh = 10;int x = 1;float f = 1.0f;double d = 2.2;String s = "hello world";MyObject myObject = new MyObject();}static short num = -5;private void calculate(int x) {// 堆数据 -> 栈数据short y = num;// 栈数据 -> 堆数据num = y;}
}

main 方法的字节码

// boolean b = true
// 从istore_1指令可以看出,将b作为int类型处理(istore含义是int store)
0 iconst_1
1 istore_1// char ch = 'a'
2 bipush 97
4 istore_2// short sh = 10
5 bipush 10
7 istore_3// int x = 1
8 iconst_1
9 istore 4// float = 1.0f
// 使用fstore,说明float类型数据和int类型数据在栈上的存储不同
11 fconst_1
12 fstore 514 ldc2_w #2 <2.2>
17 dstore 619 ldc #4 <hello world>
21 astore 823 new #5 <org/example/layout/stack/ObjectStackLayout$MyObject>
26 dup
27 invokespecial #6 <org/example/layout/stack/ObjectStackLayout$MyObject.<init> : ()V>
30 astore 932 return

main 方法的局部变量表

槽总数 = 1 + 1 + 1 + 1 + 1 + 1 + 2 + 1 + 1 = 10

在这里插入图片描述
在这里插入图片描述

总结:

  • 形参也是局部变量,测试 calculate 方法可以看到为局部变量 this 分配槽位
  • 浮点数和整数之间使用不同的字节码指令

2、在堆上的数据存储

在这里插入图片描述

2.1、Java 对象的堆内存布局

在这里插入图片描述

标记字段(Mark Word)

标记字段取决于机器字长、是否开启指针压缩这两个因素,下图是 **64 位机开启指针压缩(默认情况)**的情况
在这里插入图片描述
上面共有 5 种状态,原本应该使用 3 bit 来表示锁的状态位,这会导致处于轻量级锁状态和重量级锁状态的对象少了 1 bit 的指针,这样锁数量的上限就变为原来的 1/2。因此,将正常状态和偏向锁的最后 2bit 相同,使用额外的 1bit 来区分正常状态和偏向锁状态。

可能需要注意的点:其中有 1bit 提供给 CMS 垃圾收集器进行使用,后面在 GC 相关文章中再考虑之间的关联

在 64 位机关闭指针压缩的情况下,只是简单地将 cms使用位 弃用。
在这里插入图片描述

在 32 位机的情况下,不存在 cms使用位,同时将高位 32 bit舍弃即可。
在这里插入图片描述

元数据指针(Klass pointer)

在这里插入图片描述

hsdb 工具进行验证:

2.2、布局规则

规则优先级从高到低依次为:

  1. 对象的总长度需要对齐 8B,不够则进行零填充
  2. 父类变量在子类变量之前
  3. 引用数据类型(Object)在基本数据类型(int、double)之后
  4. 若变量类型的长度为 n,则该变量的起始偏移必须是 k × \times × n,单位为 Byte
  5. 变量可以进行重排列,不一定要按照定义的先后顺序排列(满足规则3)
  6. 类型更长的变量排在前面,类型更短的变量排在后面(满足规则3)

2.3.1、内存对齐

在没有开启指针压缩的情况下,同样会进行内存对齐,原因是 64 位机上的 CPU 缓存行大小是 8B,保证对象对齐 8B,可以保证并发情况下,两个对象的修改不会因为缓存行而相互影响。

在这里插入图片描述

2.3.2、父类优先

2.3.3、基本类型优先

2.3.4、字段对齐

2.3.5、字段重排列

2.3、测试案例

<dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.7</version>
</dependency>
class Parent {long l;int i;
}class Child extends Parent {String name;boolean b;int i;long l;
}public class ObjectHeapLayout {public static void main(String[] args) {// 测试父类中的实例变量一定在子类之前分配,并且引用类型一定在每个类的最后分配System.out.println(ClassLayout.parseInstance(new Child()).toPrintable());// 测试字符串的实际占用空间System.out.println(ClassLayout.parseInstance("123").toPrintable());// 测试数组(nums也是一个引用指针)int[] nums = new int[]{1, 2, 3};System.out.println(ClassLayout.parseInstance(nums).toPrintable());System.out.println(ClassLayout.parseInstance(new Object()).toPrintable());// System.out.println(ClassLayout.parseInstance(null).toPrintable());//抛出异常}
}

在这里插入图片描述

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

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

相关文章

2024最新docker部署gitlab

docker部署gitlab 快速命令 1 拉取镜像 docker pull gitlab/gitlab-ce2 启动容器 docker run -itd \-p 9980:80 \-p 9922:22 \-v /opt/soft/docker/gitlab/etc:/etc/gitlab \-v /opt/soft/docker/gitlab/log:/var/log/gitlab \-v /opt/soft/docker/gitlab/opt:/var/opt/g…

Vite proxy-rewrite 属性详解

在前端开发中&#xff0c;为了避免跨域问题&#xff0c;我们会在vite.config.ts 中配置如下问题 rewrite: 由于不了解Nginx的知识&#xff0c;这个属性一直困扰着我&#xff0c;这个重写有啥用&#xff0c;加和不加有啥影响 server: {host: 0.0.0.0,proxy: {/api: {target: ht…

操作系统安全:安全审计,Windows系统日志详解,Windows事件ID汇总

「作者简介」&#xff1a;2022年北京冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础对安全知识体系进行总结与归纳&#xff0c;著作适用于快速入门的 《网络安全自学教程》&#xff0c;内容涵盖系统安全、信息收集等…

从零开始安装 stable diffusion webui v1.9.3 (windows10)

从零开始安装 stable diffusion webui v1.9.3 (windows10) CUDA 安装 CUDA 12.1 | https://developer.nvidia.com/cuda-toolkit-archive CUDNN 8.x | https://developer.nvidia.com/rdp/cudnn-archive 安装路径 F:/CUDA/v12.1 安装git git官网 | https://git-scm.com/ 安…

数据结构-二叉搜索树(BST)

目录 什么是二叉搜索树 二叉搜索树的特性 (1)顺序性 (2)局限性 二叉搜索树的应用 二叉搜索树的操作 (1)查找节点 (2)插入节点 (3)删除节点 (4)中序遍历 什么是二叉搜索树 如图所示&#xff0c;二叉搜索树&#xff08;binary search tree&#xff09;满足以下条件。…

【EI会议|稳定检索】2024年航空航天、空气动力学与自动化工程国际会议(ICAAAE 2024)

2024 International Conference on Aerospace, Aerodynamics, and Automation Engineering 一、大会信息 会议名称&#xff1a;2024年航空航天、空气动力学与自动化工程国际会议 会议简称&#xff1a;ICAAAE 2024 收录检索&#xff1a;提交Ei Compendex,CPCI,CNKI,Google Schol…

WebGL开发框架比较

WebGL开发框架提供了一套丰富的工具和API&#xff0c;使得在Web浏览器中创建和操作3D图形变得更加容易。以下是一些流行的WebGL开发框架及其各自的优缺点。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.Three.js 优点&#xff1a…

装饰器模式、代理模式、适配器模式对比

装饰器模式、代理模式和适配器模式都是结构型设计模式&#xff0c;它们的主要目标都是将将类或对象按某种布局组成更大的结构&#xff0c;使得程序结构更加清晰。这里将装饰器模式、代理模式和适配器模式进行比较&#xff0c;主要是因为三个设计模式的类图结构相似度较高、且功…

VitePress 构建的博客如何部署到 github 平台?

VitePress 构建的博客如何部署到 github 平台&#xff1f; 1. 新建 github 项目 2. 构建 VitePress 项目 2.1. 设置 config 中的 base 由于我们的项目名称为 vite-press-demo&#xff0c;所以我们把 base 设置为 /vite-press-demo/&#xff0c;需注意前后 / export default…

Docker容器:搭建LNMP架构

目录 前言 1、任务要求 2、Nginx 镜像创建 2.1 建立工作目录并上传相关安装包 2.2 编写 Nginx Dockerfile 脚本 2.3 准备 nginx.conf 配置文件 2.4 生成镜像 2.5 创建 Nginx 镜像的容器 2.6 验证nginx 3、Mysql 镜像创建 3.1 建立工作目录并上传相关安装包 3.2 编写…

java案例-读取xml文件

需求 导入依赖 <dependencies><!-- dom4j --><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency> </dependencies>代码 SAXReader saxReade…

进迭时空宣布开源RISC-V芯片的AI核心技术

仟江水商业电讯&#xff08;4月29日 北京 委托发布&#xff09;4月29日&#xff0c;在“创芯生生不息——进迭时空2024年度产品发布会”上&#xff0c;进迭时空CEO、创始人&#xff0c;陈志坚博士宣布将开源进迭时空在自研RISC-V AI CPU上的核心技术&#xff0c;包括AI扩展指令…

无人机+集群组网+单兵图传:空地一体化组网技术详解

空地一体化组网技术是一种结合了无人机、集群自组网和单兵图传等多种技术的先进通信解决方案。这种技术方案的主要目的是在前线事故现场和后方指挥中心之间建立一个高效、稳定的通信链路&#xff0c;以确保信息的实时传输和指挥的顺畅进行。 首先&#xff0c;前端视频采集部分&…

自适应信号处理基础及应用——DSP学习笔记五

本专栏的图片内容都来自于老师讲课的PPT&#xff0c;本篇博客只是我个人对于上课内容的知识结构分析和梳理。 导论 自适应系统的定义、特征、形式、举例 特征 非自适应系统 • 固定参数的设计方法 • 假定事先知道了一切可能的输入条件&#xff1b;在这些条件下怎样动作&#…

word 表格 文字 上下居中

问题 word 表格 文字 上下居中 详细问题 笔者进行word 文档编辑&#xff0c;对于表格中的文本内容&#xff0c;如何进行上下居中&#xff1f; 解决方案 步骤1、选中需要进行操作的单元格 步骤2、右键 → \rightarrow →点击表格属性 步骤3、依次点击单元格 → \rightar…

Qt绘图与图形视图之自定义图元实现拖拽、拉伸、旋转功能

往期回顾 Qt绘图与图形视图之移动鼠标手动绘制任意多边形的简单介绍-CSDN博客 Qt绘图与图形视图之场景、视图架构的简单介绍-CSDN博客 Qt绘图与图形视图之基本图元绘制的简单介绍-CSDN博客 Qt绘图与图形视图之自定义图元实现拖拽、拉伸、旋转功能 一、最终效果 实现对自定义图…

应用层协议了解

一 HTTP前置知识 这篇博客会有点长&#xff0c;但对我来说非常有意义&#xff0c;这是我从一无所知到理解网络的重大突破&#xff0c;在前两个月我对网络非常恐惧&#xff0c;还十分不理解什么是网络&#xff0c;什么是协议。接下来先介绍几个概念。 1 流量 我们把数据给别人&…

GitHub Desktop进行汉化

第一步下载github桌面版 官网&#xff1a;安装 GitHub Desktop - GitHub 文档 历史版本&#xff1a;https://github.cn.uptodown.com/windows/versions 本期下载版本3.3.11进行汉化&#xff0c;最新版不一定稳定。 网站打不开的可自取&#xff1a; 3.3.11版本安装包链接&a…

【论文笔记】Language Models are Few-Shot Learners B部分

Language Models are Few-Shot Learners B 部分 回顾一下第一代 GPT-1 &#xff1a; 设计思路是 “海量无标记文本进行无监督预训练少量有标签文本有监督微调” 范式&#xff1b;模型架构是基于 Transformer 的叠加解码器&#xff08;掩码自注意力机制、残差、Layernorm&#…

排序算法:插入、希尔、选择、推排、冒泡、快速、归并排序

排序算法 目录 前言 一、排序的概念 1.1排序的概念 1.2 常见的排序算法 二、常见排序算法的实现 2.1 插入排序 2.2 希尔排序 2.3 选择排序 2.4 堆排序 2.5 冒泡排序 2.6 快速排序 2.6.1 hoare版本 2.6.2 前后指针版本 2.6.3 非递归版本 2.7 归并排序 归并排序 2.8 计数排序 三、…