Java对象的内存布局详细介绍
作者:每天都要进步一点点 发布时间:2021-07-28 05:11:38
在HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
一、对象头
Java对象的对象头由三部分组成:
1)、Mark Word
MarkWord用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC分代年龄、同步锁信息、偏向锁标识等等。Mark Word在32位JVM中的长度是32bit,在64位JVM中长度是64bit。
通常我们都是使用的64位的JVM,Mark Word 在64位 JVM 中内部结构如下图:
2)、类型指针
类型指针指向对象的类元数据,虚拟机通过这个指针确定该对象是哪个类的实例。Java对象的类数据保存在方法区。
3)、数组长度(只有数组对象才有)
如果对象是一个数组,那么对象头还需要有额外的空间用于存储数组的长度。如果对象是数组类型,因为JVM虚拟机可以通过Java对象的元数据信息确定Java对象的大小,但是无法从数组的元数据来确认数组的大小,所以用一块来记录数组长度。
二、实例数据
实例数据部分存放类的属性数据信息,包括父类的属性信息。
通过示例说明每个区域具体存放哪些内容:
class Student {
private String name;
public Student(String name) {
this.name = name;
}
}
public class Demo {
public static void main(String[] args) {
Student studentA = new Student("zhangsan");
Student studentB = new Student("lisi");
}
}
JVM结构图如下所示:
三、对齐填充
由于虚拟机要求对象起始地址必须是8字节的整数倍,所以后面有几个字节用于把对象的大小补齐至8字节的整数倍,没有特别的功能,对齐填充不是必须存在的,仅仅是为了字节对齐。
为什么必须是8个字节?
根据“计算机组成原理”,8个字节是计算机读取和存储的最佳实践。
四、使用JOL工具分析对象内存布局
接下来我们使用JOL(Java Object Layout)工具,它是一个用来分析JVM中Object布局的小工具。包括Object在内存中的占用情况,实例对象的引用情况等等。
直接在maven工程中加入对应的依赖:
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
通过JOL查看new Object()的对象布局信息:
public class JOLDemo {
public static void main(String[] args) {
Object obj = new Object();
System.out.println("十进制hashCode = " + obj.hashCode());
System.out.println("十六进制hashCode = " + Integer.toHexString(obj.hashCode()));
System.out.println("二进制hashCode = " + Integer.toBinaryString(obj.hashCode()));
String str = ClassLayout.parseInstance(obj).toPrintable();
System.out.println(str);
}
}
运行结果如下:
十进制hashCode = 1956725890
十六进制hashCode = 74a14482
二进制hashCode = 1110100101000010100010010000010
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 82 44 a1 (00000001 10000010 01000100 10100001) (-1589345791)
4 4 (object header) 74 00 00 00 (01110100 00000000 00000000 00000000) (116)
8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
解释下各个字段的含义:
OFFSET是偏移量,也就是到这个字段位置所占用的字节数;
SIZE是后面类型的大小;
TYPE是Class中定义的类型;
DESCRIPTION是类型的描述;
VALUE是TYPE在内存中的值;
从上图可以看出Object obj = new Object();在内存中占16个字节,注意最后面的(loss due to the next object alignment)其实就是对齐填充的字节数,这里由于Object obj = new Object();没有实例数据,对象头总共占用了12个字节(默认开启了指针压缩-XX:+UseCompressedOops),由于虚拟机要求对象起始地址必须是8字节的整数倍,所以还需要对齐填充4个字节,达到2倍的8bit。
来源:https://weishihuai.blog.csdn.net/article/details/126281978
猜你喜欢
- 事件:定义了事件成员的类允许通知其他其他对象发生了特定的事情。具体的说,定义了事件成员的类能提供以下功能1.方法能登记它对事件的关注2.方法
- SpringMVC获取表单数据1、实体类package cn.hadron.bean;import java.io.Serializable
- 本文实例为大家分享了struts2和hibernate实现登录和注册功能,供大家参考,具体内容如下1、该项目使用MySQL数据库,数据库名为
- java常量池是一个经久不衰的话题,也是面试官的最爱,题目花样百出,这次好好总结一下。理论先拙劣的表达一下jvm虚拟内存分布:程序计数器是j
- 前言在介绍Dubbo之前先了解一下基本概念:Dubbo是一个RPC框架,RPC,即Remote Procedure Call(远程过程调用)
- 本文实例汇总了Java性能优化技巧。分享给大家供大家参考。具体分析如下:这里参考了些书籍,网络资源整理出来,适合于大多数Java应用在JAV
- /// <summary> /// 遍历Co
- Java调用Linux系统命令有时候,我们在使用Java做一些操作时,可能性能上并不能达到我们满意的效果,就拿最近工作中的遇到的一个场景来说
- 一、稀疏数组1、什么是稀疏数组当一个数组中大部分元素为0,或者为同一个值的数组时,可以用稀疏数组来保存该数组。稀疏数组,记录一共有几行几列,
- 在style中如下面那样定义:<style name="mystyle"> <item name=&
- 一、国际化准备资源文件,资源文件的命名格式如下:baseName_language_country.propertiesbaseName_l
- 在使用SpringBoot做接口访问如何做接口的限流,这里我们可以使用google的Guava包来实现,当然我们也可以自己实现限流,Guav
- 先来看我们以前利用RestTemplate发起远程调用的代码:存在下面的问题:代码可读性差,编程体验不统一参数复杂URL难以维护1. Fei
- Unity脚本自动添加头部注释就是创建.cs文件时自动添加作者名,创建时间,文件名等看示例,我们在Unity的project面板下先创建一个
- 使用Mybatis-Plus的SqlSessionFactory问题前些日子工作中出现一个问题,项目中使用了MybatisPlus,然后出现
- 抛出问题:Long a = 4l;Long b = 4l;a == b //trueLong a = 128l;Long b = 128l;
- 404这个错误真的是一言难尽!不过大多是配置文件出错,认真修改还是可以的1.web.xml配置错误:默认首页没有写的,在web.xml添加一
- 本文实例讲述了C#利用System.Uri转URL为绝对地址的方法。分享给大家供大家参考。具体分析如下:在使用ASPOSE.Word生成Wo
- 目录概述&选型单机安装配置双机主从高可用搭建启动多个NameServer 和 Broker重要参数说明可视化管理平台SpringBo
- 委托的Invoke方法用来进行同步调用。同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行。同步调用的例子: