回答
Java 对象的内存布局包括三个部分:对象头、实例数据 和 对齐填充。
- 对象头:这是对象的元数据区域,包括两个主要部分:
- Mark Word:存储对象的运行时信息,如哈希码、GC 分代年龄、锁状态等。它是动态变化的,根据对象的状态不同而变化。
- 类型指针(Class Pointer):指向对象对应的类的元数据,帮助 JVM 定位方法表等信息。
- 实例数据:存储对象的实际字段值。JVM 按照字段声明的顺序来存储这些数据,同时考虑字段类型的大小。例如,
int
占 4 字节,long
占 8 字节。JVM 可能会对数据进行对齐优化,以提高访问效率。 - 对齐填充:为了确保内存访问的高效性,JVM 会对对象的大小进行内存对齐。通常对象的大小会被调整为 8 字节或 16 字节的倍数,这样可以使下一个对象从对齐的内存地址开始,减少访问时的开销。
详解
对象头
对象头分为两个主要部分:Mark Word 和类型指针。
Mark Word
Mark Word 用于存储对象自身的运行时数据,它在 32 位 JVM 中的长度是 32bit,在 64 位JVM中长度是 64bit,Mark Word对应到C++的代码markOop.hpp
,可以从注释中看到它们的组成:
Mark Word在不同的锁状态下存储的内容不同。
-
32 位 JVM
-
64 位 JVM
虽然它们在不同位数的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的指针。
类型指针
在 Java 中,每个对象都有一个类型指针,用于指向描述对象类型的类元数据,通过这个指针,JVM 可以确定对象的字段布局、方法实现和继承结构等信息。
实例数据
实例数据是指 Java 对象中的所有实例变量(字段),这些字段在对象被创建时分配内存,并在对象的生命周期内存储实际的值。实例数据的布局和存储方式取决于对象的类定义和字段类型。包括基本数据类型和引用类型两种。
基本数据类型的字段占用固定大小的内存,如下:
类型 | 占用空间(byte) |
---|---|
boolean |
1 |
byte |
1 |
short |
2 |
char |
2 |
int |
4 |
float |
4 |
long |
8 |
double |
8 |
引用类型存储其他对象的引用,该值指向其他对象的内存地址,其占用内存大小由与 JVM 指针大小相同,在 32 位 JVM 中是 4 字节,在 64 位 JVM 中是 8 字节。
对齐填充
为了确保内存访问的高效性,JVM 会对对象的大小进行内存对齐。通常对象的大小会被调整为 8 字节或 16 字节的倍数,这样可以使下一个对象从对齐的内存地址开始,减少访问时的开销。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。