java对象的内存布局

Java对象实例内存布局理解 是CPU和Cache之间的缓冲区。在CPU进行变量的写操作时,CPU无需真正的把变量修改写到缓存中,无需等待其他CPU的反馈,而是写到Store Buffer 就不管了。但是在引入了Store Buffer后,CPU读取变量时,如果直接从缓存中读取,则可能出现 Store Buffer中存在已修改的变量,但是缓存中还是旧的数据。此时我们发现当多个CPU共享某个变量时,,需要通过总线通知并等待其他 CPU 核的响应,然后修改本身 Cache Line 的状态造成CPU的空等大大降低 CPU 的处理性能。 阅读详情

java对象内存布局简介

java对象的内存布局包含对象头、实例数据、对齐填充

对象头

  • markword:对象默认的hash码、分代年龄,锁的状态标识等。
  • class point:指向对象对应的类的元数据内存地址(堆指向方法区)。也就是指向Class的字节码。
  • length :数组对象持有的数组长度,只有数组特有。

markword

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

markword多长呢,是分虚拟机的。32位jvm的mark的长度是32,,4位jvm的markword的长度是64。具体存储的内容及内容长度如下:

32位jvm的markword存储:
在这里插入图片描述
64位jvm的markword存储:
在这里插入图片描述
上面的两个图片如何解析呢?
无锁状态下64位jvm前25bit没用到,存0;
接下来的31bit存对象的hashCode;
接下来的1bit未用到,存0;
接下来的4bit存分代年龄;
接下来的1bit存是否偏向锁;
接下来的2bit存锁标识位;
这样就知道64位的markword都存了什么东西。其他的锁状态分析与无锁状态类似。

指针

上面的markword存储的是运行时数据,比如这个对象的hashcode、锁的状态、垃圾回收信息等。
而指针中存储的的是指针,指针是干嘛的?指针是指向方法区的,说明这个对象是什么类型的。
64位jvm指针的长度是64bit。
需要注意的是,jdk1.8默认是开启压缩的,压缩完的指针就变成了32bit。可以通过参数-XX:-UseCompressedOops关闭指针压缩。

length

length中存储的是数组长度,64位jvm数组长度占32bit。

实例数据

主要是存放类的数据信息,父类的信息,对象字段属性信息。

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

对齐填充

为了字节对齐,填充的数据。不是必须的,因为对齐了就不用填充了。

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

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

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

汇总图

在这里插入图片描述

java对象的内存布局实例演示

下面写的测试代码主要打印两个对象的内存布局。一个是普通对象student,一个是数据对象strings。

代码如下:

  • 引入java内存对象的工具包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-demo</artifactId>
        <groupId>org.ludengke</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>study</artifactId>
<dependencies>

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

</project>
  • 测试类
package binary;

import org.openjdk.jol.info.ClassLayout;

/**
 * @author ludengke
 * @title: TestObjectStruct
 * @projectName springcloud-demo
 * @description: 测试java对象的内存布局
 * @date 2021/12/1922:07
 */
public class TestObjectStruct {
    static Student student = new Student();
    static String[] strings={"1","sdfsdf","232"};

    /**
     * 查看对象内部信息: ClassLayout.parseInstance(obj).toPrintable()
     * 查看对象外部信息:包括引用的对象:GraphLayout.parseInstance(obj).toPrintable()
     * 查看对象占用空间总大小:GraphLayout.parseInstance(obj).totalSize()
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("student的结构:");
        System.out.println(student.hashCode());//对象的hashcode
        System.out.println(Integer.toHexString(student.hashCode()));//hashcode的16进制
        System.out.println(ClassLayout.parseInstance(student).toPrintable());//打印java对象内存布局
        System.out.println("strings的结构:");
        System.out.println(strings.hashCode());//对象的hashcode
        System.out.println(Integer.toHexString(strings.hashCode()));//hashcode的16进制
        System.out.println(ClassLayout.parseInstance(strings).toPrintable());//打印java对象内存布局

    }
}

  • 执行结果
    在这里插入图片描述

  • 结果解析

这张图是64位虚拟机,未进行指针压缩的执行结果。

图中输出了两个对象,一个是普通对象的student对象,一个是数组对象strings对象。数组对象中多了数组长度。

student对象的说明信息比较多,详细说明了对象头、实例数据、填充数据。可以由于图片篇幅有限,将前8位的说明画到string对象中。

为什么图片中的说明与上面《64位jvm的markword存储》图片的顺序不一致呢,正好是倒序?
这是涉及到一个知识点大端存储与小端存储,这里不详细叙述。我们这里之所以倒序,是因为大端存储的原因。

其它锁状态的验证有空再研究。

参考博客:
https://blog.youkuaiyun.com/baidu_28523317/article/details/104453927
https://www.cnblogs.com/jajian/p/13681781.html

Modbus协议全家桶(C#纯原生完整版):ModbusRTU + ModbusTCP + ModbusASCII 协议规范+完整封装+工业级实战 你已经掌握了C#串口/网口原生核心API和工业通信协议本质,而今天的主角Modbus协议,是工业通信领域绝对的王者、通用的标准、入门的必修课,没有之一。凡是做工业通信开发,必会Modbus协议;市面上99%的工业设备(PLC、变频器、温控仪、传感器、流量计、扫码枪)都原生支持Modbus协议。Modbus协议不是单一协议,而是一个「协议家族」,我们常说的就是这个家族的三大核心成员,也是工业现场的全部Modbus应用形态。 阅读详情

相关推荐

Calpuff模型实战:从气象数据预处理到污染物扩散模拟全流程指南

本文提供了一份详尽的Calpuff模型实战指南,涵盖从气象数据预处理、地形处理到污染物扩散模拟与结果可视化的全流程。重点解析了Calmet气象场构建、Calpuff核心参数配置,并与AERMOD模型进行对比,帮助环境工程师与科研人员掌握这一强大的三维非稳态拉格朗日扩散模型,以应对复杂地形、海岸熏烟等实际模拟挑战。

s4t5u6v7的博客 458

Java 对象的内存布局

作为一名 Java 程序员,我们在日常工作中使用这门面向对象的编程语言时,做的最频繁的操作大概就是去创建一个个的对象了。对象的创建方式有很多,可以通过 new、Spring 管理 Bean、反射、clone、反序列化等不同方式来创建,但最终使用时对象都要被放到内存中,那么你知道在内存中的 Java 对象是由哪些部分组成以及是怎么存储的吗?这篇文章可带你深入了解 Java 对象的内存布局。

流华追梦的专栏 1964

Python+Seaborn可视化:双因素方差分析结果这样呈现更专业

本文详细介绍了如何利用Python中的Seaborn和statsmodels库,专业地执行并可视化双因素方差分析结果。通过模拟实验数据,演示了从模型构建、统计检验(包括交互作用分析)到诊断验证的全流程。重点展示了如何使用Seaborn绘制交互效应图、组合分布图及热图,将复杂的统计结果转化为直观、富有洞察力的可视化图表,助力科研论文与商业报告的专业呈现。

weixin_29274969的博客 137

Java 对象内存布局详解

如果逃逸分析证明一个对象不会被其他线程访问到,并且这个对象可以再分,那么创建的时候就不会创建这个对象,而是使用若干个基本类型的标量数据来替换它。JVM 堆中所有对象分配的内存字节总数必须是 8N,如果对象头和实例数据占用的总大小不满足要求,则需要通过对齐数据来填满。不过继承自父类的私有成员变量也需要初始化,子类对象创建的时候会调用父类构造方法来完成这部分工作,但不会创建出父类对象。是对象头中非常关键的一部分,其在 JVM 中结构如下图所示,读者如感兴趣可以参考。在JVM 1.8 版本后,虚拟机默认开启。

谈谈1974 3331

告别版本过低提示!微信3.9登录修复与聊天记录无缝迁移全攻略

本文详细解析了微信3.9版本过低提示的根源,并提供了完整的修复方案和聊天记录迁移指南。通过专用修复工具绕过版本检测,以及新旧版本聊天记录目录对比,帮助用户实现无缝迁移。特别提醒备份重要数据,确保操作安全。

weixin_42535461的博客 3123

如何用Hugo Stack主题打造极简技术博客?3个必改配置与5个高级美化技巧

本文详细解析了如何深度定制Hugo Stack主题,打造个性化技术博客。文章提供了3个必改配置与5个高级美化技巧,涵盖字体美学、布局重构、代码块视觉强化及细节打磨,帮助开发者超越基础部署,实现从功能到美学的进阶,提升博客质感与用户体验。

carrot的博客 568

Java对象的内存布局

使用句柄方式最大的好处就是reference中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要被修改。由于reference类型在Java虚拟机规范里只规定了一个指向对象的引用,并没有定义这个引用应该通过哪种方式去定位,以及访问到Java堆中的对象的具体位置,因此不同虚拟机实现的对象访问方式会有所不同,主流的访问方式有两种:使用句柄和直接指针。使用直接指针方式最大的好处就是速度更快,他节省了一次指针定位的时间开销。

杀神lwz的博客 513

openclaw 保姆级部署与核心玩法解析:国产DeepSeek模型 + 飞书

OpenClaw是一款功能强大的开源AI个人助理,支持全平台私有化部署,数据完全本地掌控。它不仅可通过聊天窗口直接操控电脑(安装软件、创建项目),还支持接入飞书等主流通讯工具,化身24小时在线的智能助理。本文提供了从零开始的详细部署教程,涵盖基础安装、模型配置(如GLM-4、DeepSeek)到飞书集成的完整实战指南,助你将这款“核动力”AI助手快速融入日常工作流。

甘蓝的专栏 2997

Java对象内存布局详解

对象头(Header)实例数据(Instance Data)对齐填充(Padding)这种内存布局是JVM管理对象和实现多线程同步的基础,理解它有助于编写高效的Java代码和解决性能问题。Java对象内存布局是JVM内部实现的关键部分,它直接影响了Java程序的内存使用效率和并发性能。通过理解对象头(特别是Mark Word)的结构和变化,我们可以更好地理解Java的锁机制和synchronized关键字的工作原理,从而编写更高效的Java程序。

左灯右行的爱情 1054

1. 在 SAP ABAP 事物码 SEGW 里创建 SAP OData 项目

本文介绍如何在 SAP ABAP 事物码 SEGW 里创建 SEGW 项目,使用工具生成 Runtime 运行时需要的资源。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 5435

实现航迹关联的三种JPDA算法及Matlab代码

本文介绍了三种不同的JPDA算法实现航迹关联,并提供相应的Matlab代码。卡尔曼滤波是一种常用的状态估计算法,其基本思想是根据系统模型和观测数据,通过迭代计算来更新系统状态的估计值。基于卡尔曼滤波的JPDA算法是指在航迹关联问题中,同时利用卡尔曼滤波器的状态估计和概率假设,从而确定目标之间的关联关系。基于粒子滤波的JPDA算法是指在航迹关联问题中,通过抽样生成一组粒子(代表系统的不同可能状态),从而计算目标之间的关联概率。基于启发式搜索的JPDA算法是指在航迹关联问题中,通过多次迭代寻找最优关联方案。

code_welike的博客 1831

Java对象内存布局

一、Java对象内存布局 Java对象的内存布局:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。无论是32位还是64位的HotSpot,使用的都是8字节对齐。也就是说每个java对象,占用的字节数都是8的整数倍,(对象头 + 实例数据 + padding)% 8等于0且0 <= padding < 8。 1、基本数据类型占用的字节数,JVM规范中有明确的规定,无论是在32位还是64位的虚拟机,占用的内存大小是相同的。 2、...

fengchengwu2012的博客 5746

Python 爬虫实战:华尔街见闻精选文章爬取(反反爬 + 投资情绪分析)

Python 爬虫实战:华尔街见闻精选文章爬取(反反爬 + 投资情绪分析)

yansideyucsdn的博客 969

JVM——Java对象的内存布局

JVM——Java对象的内存布局

从知识输入到知识输出 1456

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java对象内存布局概述

以HotSpot虚拟机为例,对象在内存中可以分为三块区域:对象头、实例数据和对齐填充。其中,对象头包含Mark Word和类型指针,关于对象头的内容,在gitchat中对其实现和原理都已经结合openjdk源码进行了详细的说明,其也不是本博文的主题,这里就不细说了;实例数据部分则是对象真正存储的有效信息,包含代码中所定义的字段内容;对齐填充则不是必须存在的,只是起占位符的作用,比如Hot Spot...

黄智霖的博客 9519

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Java对象在内存中的内存布局

一.Java对象的内存占用大小 为了方便在程序中看到java对象内存布局,我们可以在maven中添加jol-core依赖 <dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.9</version> </dependency> 首先我们看下最简单的Object对象是怎么

我唤来了星繁,似灭似绚烂 5365

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Java对象在内存中的布局

上篇讲了一下对象创建底层步骤细节,那创建完的对象在内存中是什么样的?本篇继续讲一下对象的内存布局 在虚拟机中,对象在内存中的存储布局可分为三块:对象头、实例数据和对齐填充 1、对象头 对象头用于存储对象的元数据信息 对象头又可以分为两块内容:第一部分用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,这部分数据...

曹举的个人博客 2817

Java对象在内存中的布局详解

对象在内存中的布局详解

Mr_linsir的博客 1140

JAVA对象在内存中的布局

一、要区分普通对象和数组Java对象在内存中的具体空间大小取决于JVM的实现和配置,但我们可以给出一个大致的概念。以下是基于常见的HotSpot JVM(Oracle/OpenJDK)的一些典型值:对象头(Object Header):其中,Mark Word 和 Klass Pointer 各自占据一部分:实例数据(Instance Data):对齐填充(Padding):举个例子,假设有一个简单的类,只有一个int类型的成员变量,在64位系统上的对象大小可能是这样的:所以总大小就是16字节。请注意,这些

诗人不写诗 716
上一篇: 计算机的单位
下一篇: idea 导出某个类的jar
ludkjava
博客等级 码龄11年 173粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值