对象的内存布局

对象内存布局

在Hotspot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头,实例数据,对齐填充。

1.对象头

1.1 存储对象自身的运行时数据(mark word):哈希码,gc分代年龄。

 1.2 Class指针:通过该指针确定该对象是哪个类的实例。

 在64位系统中,class指针占4B,mark word在开启指针压缩的时候占4B;未开启指针压缩的时候占8B.  在32位系统下,上面两部分各占4B;

 

2.实例数据

 默认分配策略:long/double ->  int/float -> short/char -> byte/boolean -> Reference

 如果设置了-XX:FieldsAllocationStyle=0(默认是1),那么引用就会放在最前面:Reference -> long/double ->  int/float -> short/char -> byte/boolean

 结论:分配策略总是按照宽度由大到小的顺序排列,相同宽度的放在一起。

 在有继承关系的对象中,只有一个头部,父类的属性分配到该对象中,这样才能通过父类访问他的属性。如果开启CompactFields,那么,子类中较窄的变量就会插到父列的变量的空隙中。

 [[注]] 静态属性所占的空间通常不计算到对象本身的空间中,以为他的引用是在方法区。

 属性的对齐,例如byte占用一个字节的空间,那么就会填充3字节实现对齐。(32bit系统)

3.对齐填充

Hotspot虚拟机要求java对象起始地址必须是8的整数倍,所有Java对象在内存中将以8字节对齐,也就是对象的总大小必须是8字节的整数倍。

对象的访问定位

程序通过栈上的引用来操作堆上的具体对象,访问方式有两种。

句柄访问方式:java堆中将划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。

指针访问方式:reference变量中直接存储的就是对象的地址,而java堆对象一部分存储了对象实例数据,另外一部分存储了对象类型数据。

这两种访问对象的方式各有优势,使用句柄访问方式最大好处就是reference中存储的是稳定的句柄地址,在对象移动时只需要改变句柄中的实例数据指针,而reference不需要改变。使用指针访问方式最大好处就是速度快,它节省了一次指针定位的时间开销,就虚拟机而言,它使用的是第二种方式(直接指针访问)。

时间: 2024-11-05 02:17:18

对象的内存布局的相关文章

Java对象的内存布局

Java对象的内存布局:对象头(Header),实例数据(Instance Data),对齐填充(Padding):另外:不同的环境结果可能有差异,我所在的环境是HotSpot虚拟机,64位Windows. 对象头 对象头在32位系统上占用8bytes,64位系统上占用16bytes. System.out.println("sizeOf(new Object()) = " + sizeOf(new Object())); sizeOf(new Object()) = 16 实例数据

C++ 对象的内存布局(上)

C++ 对象的内存布局(上) 陈皓 http://blog.csdn.net/haoel 点击这里查看下篇>>> 前言 07年12月,我写了一篇<C++虚函数表解析>的文章,引起了大家的兴趣.有很多朋友对我的文章留了言,有鼓励我的,有批评我的,还有很多问问题的.我在这里一并对大家的留言表示感谢.这也是我为什么再写一篇续言的原因.因为,在上一篇文章中,我用了的示例都是非常简单的,主要是为了说明一些机理上的问题,也是为了图一些表达上方便和简单.不想,这篇文章成为了打开C++对象模

c++对象模型是什么,对象的内存布局和结构问题

在c++发明的初期对于c++对象模型的争论从来没有停止过直到标准委员会通过了最终的c++对象模型这件事情才变得尘埃落定.C++对象模型可能是最不需要去解释的,但是又是不得不去说的因为c++的入门最先接触的就是c++对象.在上个世纪一共有三种c++对象模型,它们的出现可以说是一个不断优化的过程最终只有我们目前看到的c++对象模型在使用.了解c++对象模型非常重要,了解之后对于对象的内存布局,内存大小,虚函数以及静态数据成员和成员函数的理解有非常巨大的帮助.言归正传,下面就来分别讨论c++的三种对象

java对象的内存布局(一):计算java对象占用的内存空间以及java object layout工具的使用

最近在学习java对象内存布局方面的一些知识,主要是想知道一个java对象到底占用多少内存空间,以及java对象在内存中到底是什么样子的.c/c++中的sizeof运算符能够方便地告诉我们一个变量占用的内存空间,但是在java中却没有直接提供这种机制.如果想获取java对象占用的内存大小,可以利用java的Instrumentation机制.java.lang.instrument.Instrumentation这个接口提供了getObjectSize(Object objectToSize),

win x64下C++对象的内存布局的学习

这篇文章是在学习陈皓的一篇文章<C++对象的内存布局(上)>后,针对x64的下情况的学习笔记.他的文章的链接地址是:http://blog.csdn.net/haoel/article/details/3081328. 他的示例代码中有下列片段: 如果在vs2015社区版中以debug方式编译出x64版本的exe运行后会崩溃.经过调试发现在x64下地址是以unsigned long long表示的(如果测试发现,编译后台实际上会把unsigned long long 转换为unsigned _

C++ 对象的内存布局(上)

转自陈皓的博客 前言 在谈论虚函数表里,至少有以下这些内容没有涉及: - 有成员变量的情况. - 有重复继承的情况. - 有虚拟继承的情况. - 有钻石型虚拟继承的情况. 所以,这篇文章将会是<C++虚函数表解析>的一个续篇,也是一篇高级进阶的文章. 对象的影响因素 简而言之,我们一个类可能会有如下的影响因素: 成员变量 虚函数(产生虚函数表) 单一继承(只继承于一个类) 多重继承(继承多个类) 重复继承(继承的多个父类中其父类有相同的超类) 虚拟继承(使用virtual方式继承,为了保证继承

C++ 对象的内存布局—— 虚继承下的虚函数

C++ 对象的内存布局(下)这篇文章的"单一虚拟继承"和"钻石型虚拟继承"时的类内存布局讲得不太清楚,我有一处疑问,我用的是VS2005.因此记录一下. 类继承图例如以下: 这里:类B被类B1和B2虚拟继承,而B1和B2同一时候被D继承. B1的f().B2的f()覆盖了B的f(): D的f()覆盖了B1的f(),D的f1()覆盖了B1的f1() D的f()覆盖了B2的f(),D的f2()覆盖了B2的f2() 类代码例如以下: class B { public: i

C++对象模型之详述C++对象的内存布局

在C++对象模型之简述C++对象的内存布局一文中.详细分析了各种成员变量和成员函数对一个类(没有不论什么继承的)对象的内存分布的影响,及详细解说了怎样遍历对象的内存,包含虚函数表.假设你在阅读本文之前.还没有看过C++对象模型之简述C++对象的内存布局一文,建议先阅读一下.而本文主要讨论继承对于对象的内存分布的影响,包含:继承后类的对象的成员的布局.继承对于虚函数表的影响.virtual函数机制怎样实现.执行时类型识别等. 因为在C++中继承的关系比較复杂.所以本文会讨论例如以下的继承情况: 1

JVM——深入分析对象的内存布局

概述 一个对象本身的内在结构需要一种描述方式,这个描述信息是以字节码的方法存储在方法区中的.Class 本身就是一个对象,都以 KB 为单位,如果 new Integer() 为了表示一个数据就占用KB级别的内存就有点不值了,下面讲解 JVM 是如何做的.为了表示对象的属性.方法等信息,不得不需要结构描述.Hotspot VM 使用对象头部的一个指针指向 Class 区域的方式来找到对象的 Class 描述,以及内部的方法.属性入口.如下图所示: 在 HotSpot 虚拟机中,对象在内存中存储布

Java对象的内存布局以及对象的访问定位

先来看看Java对象在内存中的布局 一 Java对象的内存布局 在HotSpot虚拟机中,对象在内存中的布局分为3个区域 对象头(Header) Mark Word(在32bit和64bit虚拟机上长度分别为32bit和64bit)存储对象自身的运行时数据,包括哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时 间戳等 类型指针 即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例.但是并不是所有类型虚拟机实现都必须在对象数据上保留类型指针,如果对象是一