java对象内存结构分析与大小计算

news2024/11/15 17:17:04

java对象内存结构

Java对象保存在堆中时,由三部分组成:

  1. 对象头(object header):包括了关于堆对象的布局、类型、GC状态、同步状态和标识哈希码的基本信息。所有java对象都有一个共同的对象头格

  1. 实例数据(Instance Data):主要是存放类的数据信息,父类的信息,对象字段属性信息。

  1. 数据长度(array length):记录了数组的长度(只有对象是数组时才有这个结构)。

  1. 对齐填充(Padding):为了字节对齐成的8倍数,填充的数据,不是必须的。

什么是对象头?

我们可以在Hotspot官方文档中找到它的描述。从中可以发现,它是Java对象和虚拟机内部对象都有的共同格式,由两个(计算机术语)组成。另外,如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是从数组的元数据中无法确定数组的大小。

它里面提到了对象头由两个组成,这两个分别是 mark wordklass pointer

什么是mark word

用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等。

Mark Word在32位JVM中的长度是32bit,在64位JVM中长度是64bit。

虽然它们在不同位数的JVM中长度不一样,但是基本组成内容是一致的。

  • 锁标志位(lock):区分锁状态,11时表示对象待GC回收状态, 只有最后2位锁标识(11)有效。

  • biased_lock:是否偏向锁,由于正常锁和偏向锁的锁标识都是 01,没办法区分,这里引入一位的偏向锁标识位。

  • 分代年龄(age):表示对象被GC的次数,当该次数到达阈值的时候,对象就会转移到老年代。

  • 对象的hashcode(hash):运行期间调用System.identityHashCode()来计算,延迟计算,并把结果赋值到这里。当对象加锁后,计算的结果31位不够表示,在偏向锁,轻量锁,重量锁,hashcode会被转移到Monitor中。

  • 偏向锁的线程ID(JavaThread):偏向模式的时候,当某个线程持有对象的时候,对象这里就会被置为该线程的ID。 在后面的操作中,就无需再进行尝试获取锁的动作。

  • epoch:偏向锁在CAS锁操作过程中,偏向性标识,表示对象更偏向哪个锁。ptr_to_lock_record:轻量级锁状态下,指向栈中锁记录的指针。当锁获取是无竞争的时,JVM使用原子操作而不是OS互斥。这种技术称为轻量级锁定。在轻量级锁定的情况下,JVM通过CAS操作在对象的标题字中设置指向锁记录的指针。ptr_to_heavyweight_monitor:重量级锁状态下,指向对象监视器Monitor的指针。如果两个不同的线程同时在同一个对象上竞争,则必须将轻量级锁定升级到Monitor以管理等待的线程。在重量级锁定的情况下,JVM在对象的ptr_to_heavyweight_monitor设置指向Monitor的指针。

Klass Pointer

即类型指针,是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

实例数据

如果对象有属性字段,则这里会有数据信息。如果对象无属性字段,则这里就不会有数据。根据字段类型的不同占不同的字节,例如boolean类型占1个字节,int类型占4个字节等等;

对齐填充

对象可以有对齐数据也可以没有。默认情况下,Java虚拟机堆中对象的起始地址需要对齐至8的倍数。如果一个对象用不到8N个字节则需要对其填充,以此来补齐对象头和实例数据占用内存之后剩余的空间大小。如果对象头和实例数据已经占满了JVM所分配的内存空间,那么就不用再进行对齐填充了。

所有的对象分配的字节总SIZE需要是8的倍数,如果前面的对象头和实例数据占用的总SIZE不满足要求,则通过对齐数据来填满。

为什么要对齐数据

字段内存对齐的其中一个原因,是让字段只出现在同一CPU的缓存行中。如果字段不是对齐的,那么就有可能出现跨缓存行的字段。也就是说,该字段的读取可能需要替换两个缓存行,而该字段的存储也会同时污染两个缓存行。这两种情况对程序的执行效率而言都是不利的。其实对其填充的最终目的是为了计算机高效寻址。

java对象大小的计算(我是64位计算机 JDK8)

maven 引入如下jar包

 <dependency>
            <groupId>org.openjdk.jol</groupId>
            <artifactId>jol-core</artifactId>
            <version>0.16</version>
        </dependency>

demo code

public class ObjectTest {

    public static void main(String[] args) {
        System.out.println("****************没属性**********************");
        testOne testOne = new testOne();
        System.out.println(ClassLayout.parseInstance(testOne).toPrintable());
        System.out.println("****************有属性**********************");
        testTwo testTwo = new testTwo();
        System.out.println(ClassLayout.parseInstance(testTwo).toPrintable());
        System.out.println("****************有数组**********************");
        testTwo[] testTwoArr = new testTwo[]{new testTwo(),new testTwo()};
        System.out.println(ClassLayout.parseInstance(testTwoArr).toPrintable());
    }
}

class  testOne{

}

class  testTwo{

    private  int a;

}

结果含义

  1. OFF : 偏移地址,单位字节;

  1. SZ :占用的内存大小,单位为字节;

  1. TYPE DESCRIPTION : 类型描述,

其中object header:mark为对象头的markword;

其中object header:class为对象头的klass pointer;

其中 object alignment gap 为对齐填充

其中array length 为数组长度

由于jdk默认开启了指针压缩。
所以我们能看到object header: class 变成了4个字节。 对象头占了12个字节
可以通过配置vm参数开启关闭指针压缩,-XX:-UseCompressedOops。这时候对象头变成了16个字节


****************无属性**********************
com.tongji.testOne object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4        (object header: class)    0xf800c244
 12   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
1.对象头mark 8个字节+对象头 klass pointer 4个字节=12字节
2.由于12不是8的整数被所以需要把12填充到8的倍数
3.最接近12的能被整除的是16故需要填充4个字节 16-12=4字节。



****************有属性**********************
com.tongji.testTwo object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4        (object header: class)    0xf800cfce
 12   4    int testTwo.a                 0
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
1.对象头mark 8个字节+对象头 klass pointer 4个字节=12字节
2.类中int 占4个字节
3.12+4=16个字节 能被8整除故不需要填充

****************数组**********************
[Lcom.tongji.testTwo; object internals:
OFF  SZ                          TYPE DESCRIPTION               VALUE
  0   8                               (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4                               (object header: class)    0xf800d0dc
 12   4                               (array length)            2
 12   4                               (alignment/padding gap)   
 16   8   com.tongji.testTwo testTwo;.<elements>       N/A
Instance size: 24 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total

1.对象头mark 8个字节+对象头 klass pointer 4个字节=12字节
2.array length 占4个字节
3.elements 占8个字节
4.12+4+8=24字节

GC年龄为啥最大是15?大家猜猜是为啥!

看到前面的对象头的mark word 大家肯定都知道了 GC年龄无论在32位还是64位计算机只占了4位其最大值也就是 1111(二进制)=2^4-1=15.

平常常用的hashCode藏在哪里?

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

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

相关文章

55个软件测试工具,正在做测试的你get到了吗

网络“黑色星期五”威胁&#xff0c;安全漏洞&#xff0c;网上银行盗窃&#xff0c;系统停机时间&#xff0c;以及许多这样的恶梦让全球的企业忧心忡忡难以入眠。确保性能具有加载的安全性和增强的经验是这个领域每个有能力的玩家所必备的。 我们为你提供了一个丰富的软件测试…

Word控件Spire.Doc 【Table】教程(15):如何在 C# 中对齐表格

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

Java字符流

5 字符流 5.1 为什么出现字符流 由于字节流操作中文不是特别的方便&#xff0c;所以Java就提供字符流字符流字节流编码表用字节流复制文本文件时&#xff0c;文本文件也会有中文&#xff0c;但是没有问题&#xff0c;原因是最终底层操作会自动进行字节拼接成中文&#xff0c;…

【面试题】对JS中的事件冒泡、事件捕获、事件委托的理解

大厂面试题分享 面试题库后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★地址&#xff1a;前端面试题库DOM事件流&#xff08;event flow &#xff09;存在三个阶段&#xff1a;事件捕获阶段、处于目标阶段、事件冒泡阶段。Dom标准事件流的触发的先…

ChatGPT的原理:机器人背后的模型

ChatGPT的原理&#xff1a;机器人背后的模型 翻译&#xff1a;老齐 本文将深入讲解支持 ChatGPT 的机器学习模型。从介绍大语言模型&#xff08;Large Language Models&#xff09;开始&#xff0c;深入探讨革命性的自注意力机制&#xff0c;该机制使 GPT-3 得以被训练。然后&a…

数据库查询计划:获取与分类

数据库在得到一个查询后&#xff0c;先将查询转化为一个逻辑查询计划&#xff0c;对其进行优化&#xff0c;然后转为物理执行计划&#xff0c;最后按照物理执行计划进行操作&#xff0c;最终得到最终结果。本篇博客介绍获得数据库查询计划的语法与物理计划的分类。 目录得到查询…

文件描述符fd

目录文件描述符fd系统文件IO接口介绍openclosewriteopen的函数返回值0 & 1 & 2文件描述符的分配规则重定向dup2系统调用FILE文件描述符fd 操作系统是文件的管理者&#xff0c;所有语言上的对“文件”的操作&#xff0c;都必须贯穿OS&#xff0c;又因为操作系统不相信任…

A_A07_003 AS608指纹模块上位机软件使用

A_A07_003 AS608指纹模块上位机软件使用一、软件获取二、测试用模块与接线三、上位机界面分块和功能1、指纹图像显示区域2、硬件信息3、打开设备4、设备配置5、信息显示6、图像管理7、指纹处理8、辅助功能四、注意事项一、软件获取 网盘链接 直戳跳转 二、测试用模块与接线 …

【Kubernetes】【五】资源管理和YML

第三章 资源管理 本章节主要介绍yaml语法和kubernetes的资源管理方式 资源管理介绍 在kubernetes中&#xff0c;所有的内容都抽象为资源&#xff0c;用户需要通过操作资源来管理kubernetes。 ​ kubernetes的本质上就是一个集群系统&#xff0c;用户可以在集群中部署各种服务…

软件测试面试刷题app包含了各种难题

软件测试的生命周期&#xff1a; V模型&#xff1a;与软件开发阶段呼应 软件开发&#xff1a;需求分析-->概要设计-->详细设计-->编码阶段软件测试&#xff1a;单元测试-->集成测试-->系统测试-->验收测试从基本流程的角度讲&#xff1a; 需求阶段&#xff…

Java基础:接口

1.接口的概念 当不是所有子类, 而是多个子类都包含一个方法时, 为了代码书写规范性, 可以用自定义的接口来统一该方法的书写规范. 所以接口可以看作是一种书写规则. 接口是对行为的抽象 抽象类一般是书写在父类当中, 接口是单独书写的, 不是一种类 2.接口的定义和使用 3.接口…

MATLAB/Simulink 通信原理及仿真学习(一)

文章目录MATLAB/Simulink 通信原理及仿真学习&#xff08;一&#xff09;基本操作 (23.2.16)MATLAB 变量矩阵运算画图工具函数函数文件操作MATLAB/Simulink 通信原理及仿真学习&#xff08;一&#xff09; 基本操作 (23.2.16) MATLAB 变量 变量以字母开头&#xff0c;后接字…

Ubuntu16.04搭建Fabric1.4环境

一、换源 为了提高下载速度&#xff0c;将ubuntu的源改成国内的源&#xff08;推荐阿里云源和清华源&#xff09; apt源保存在 /etc/apt/sources.list / 代表根目录 /etc 这个文件夹几乎放置了系统的所有配置文件 1.备份 sudo cp /etc/apt/sources.list sources_backup.l…

媒体邀约之企业如何加强品牌的宣传力度

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。胡老师分享了许多媒体传播方面的经验&#xff0c;今天就跟大家分享下我对企业宣传方面的看法。企业如何加强品牌的宣传力度&#xff1a;1&#xff0c;网络宣传在社交媒体上建立企业账户&am…

Jmeter常用断言之响应断言详解

响应断言是最常用的一种断言方法&#xff0c;主要是对响应结果中的文本内容进行断言&#xff0c;比如响应结果是否包含指定的值&#xff0c;或者是否等于指定的值。响应断言可以适用各种返回类型的响应结果&#xff0c;如&#xff1a;Test、html、application/json、applicatio…

安装 cplex 求解器

安装 cplex 求解器 安装 cplex 求解器和python-docplexcplex 安装matlab 用户安装 cplexpython 版本安装 cplex 求解器和python-docplex cplex 安装 cplex 是解决优化问题的一个工具箱&#xff0c;用来线性规划、混合整数规划和二次规划的高性能数学规划求解器。可以理解成&a…

《爆肝整理》保姆级系列教程python接口自动化(十六)--参数关联接口后传(详解)

简介 大家对前边的自动化新建任务之后&#xff0c;接着对这个新建任务操作了解之后&#xff0c;希望带小伙伴进一步巩固胜利的果实&#xff0c;夯实基础。因此再在沙场实例演练一下相关接口。我们用自动化发随笔之后&#xff0c;要想接着对这篇随笔操作&#xff0c;不用说就需 …

实现聊天消息绘制、图文混排(源码,支持Windows、Linux)

在实现聊天软件时&#xff0c;渲染文字表情图文混排是一项非常繁琐的工作&#xff0c;再加上还要支持GIF动图、引用消息、撤回消息、名片等不同样式的消息渲染时&#xff0c;就更加麻烦了。 好在我们可以使用 ESFramework 提供的 IChatRender 组件&#xff0c;使用它我们就能轻…

小众免费的短视频素材库

推荐5个小众但好用的视频素材网站&#xff0c;免费可商用&#xff0c;视频剪辑、自媒体必备~ 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYxMjky ​ 菜鸟图库网素材非常丰富&#xff0c;网站主要还是以设计素材为主&#xff0c;高清视频素材也很多&#xff0c;像风…

(考研湖科大教书匠计算机网络)第四章网络层-第六节3:开放最短路径优先OSPF的基本工作原理

获取pdf&#xff1a;密码7281专栏目录首页&#xff1a;【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一&#xff1a;OSPF概述&#xff08;1&#xff09;概述&#xff08;2&#xff09;细节阐述A&#xff1a;链路状态和代价B&#xff1a;问候分组和邻居表C&#xff…