Java对象存储内存布局详解
Java 是一门面向对象的编程语言,因此在 Java 程序中创建对象是很常见的。在 Java 虚拟机(JVM)中,对象在内存中是如何存储和布局的呢?接下来我们将详细介绍 Java 对象存储内存布局的实现。
Java对象存储
Java 对象有两种主要的存储区域:堆和栈。
-
堆:是 Java 程序中最常见的内存区域,用来存储所有的对象和数组。所有的线程共享 Java 堆。
-
栈:是线程私有的内存区域。它用来存储线程运行时的栈帧。每个栈帧(Stack Frame)存储一个方法(Method)的局部变量表、操作数栈和帧数据(Frame Data)。
Java对象内存布局
Java 对象在内存中的布局由三部分组成:对象头(Header)、实例数据(Instance data)和对齐填充(Padding)。
对象头(Header)
对象头是对象在内存中的开头部分,包含两个部分的数据:标记字(Mark Word)和类型指针(Klass Pointer)。
-
标记字(Mark Word):包含了对象的哈希码、锁状态、分代年龄等信息。大多数的 JVM 实现使用32位的标记字,但在一些具有大内存支持的 JVM 中,可以使用64位标记字。
-
类型指针(Klass Pointer):用于指向对象所属的类,也称为 Class Metadata Address。
实例数据(Instance data)
实例数据是指对象实际存储的数据部分,即程序员自定义的成员变量和方法。
对齐填充(Padding)
对齐填充(Padding)是指填充字节,用于占用一定的内存,以对齐下一个对象。Java 要求对象在内存中的起始地址必须是8的倍数,因此为了达到这个要求,JVM需要额外的填充一些字节。
示例说明
下面两个示例用于说明 Java 对象的内存布局。
示例一
public class Test {
private int i;
private Object obj;
}
对于这个示例,Test 类实例化后占用的内存空间如下:
对象头:markword(32位)+ klass pointer(32位)= 8字节
实例数据:int i(4字节)+ object obj(4字节)= 8字节
对齐填充:不需要填充
--------------------------------------
总共:8字节
示例二
public class Test {
private int i;
private Object obj;
private byte b;
}
对于这个示例,Test 类实例化后占用的内存空间如下:
对象头:markword(32位)+ klass pointer(32位)= 8字节
实例数据:int i(4字节)+ object obj(4字节)+ byte b(1字节)= 9字节
对齐填充:填充3字节
--------------------------------------
总共:20字节
对于这两个示例,我们可以看到对象头和实例数据不难理解,重点是对齐填充的理解,这是因为按内存对齐要求,每个对象在内存中的数值地址都应该是8的倍数,如此可能会带来空间浪费。因此,jvm会通过对齐填充的方式,来补齐空间,保证每个对象的内存地址都能够是8的倍数,达到了对性能的优化效果。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java对象存储内存布局详解 - Python技术站