本文目录#
对象在内存中的组成#
HotSpot 中的 Java 对象由三部分组成:
- 对象头 (Header):包括 Mark Word 与 Klass Pointer;数组对象还包含长度字段。
- 实例数据 (Fields):按照声明顺序、对齐填充;受
-XX:FieldsAllocationStyle、-XX:+UseCompressedOops影响。 - 对齐填充 (Padding):保证对象大小为 8 字节倍数。
Mark Word 结构#
Mark Word 存储对象运行时信息,取决于对象所处状态:
| 位宽 | 内容 |
|---|---|
| 32/64 bit | 哈希码、GC 分代年龄、锁标志位、偏向锁线程 ID 与时间戳 |
锁状态迁移:无锁 → 偏向锁 → 轻量级锁 → 重量级锁。-XX:+PrintBiasedLockingStatistics 可观察偏向锁。JDK 15 默认关闭偏向锁,可通过 -XX:+UseBiasedLocking 开启。
压缩指针(Compressed Oops)#
- 默认在 64 位 JVM、堆小于 32GB 时启用,减少对象头与引用占用。
- 通过
-XX:-UseCompressedOops关闭;类指针压缩由-XX:+UseCompressedClassPointers控制。 - 对象地址计算:
(narrow_oop << 3) + base,节省内存同时保持 8 字节对齐。
工具与实战#
java -XX:+PrintCommandLineFlags查看压缩指针状态。- 使用 JOL(Java Object Layout)验证对象占用:
1 | System.out.println(ClassLayout.parseInstance(new Object()).toPrintable()); |
- GC 日志中的
Heap: 1G(4G)等信息可辅助判断对象分配与存活。
自检清单#
- 是否了解对象头在不同锁状态下的变化?
- 是否评估压缩指针对性能与内存的影响?
- 是否利用 JOL 等工具验证关键数据结构的内存占用?
参考资料#
- HotSpot 虚拟机对象布局文档:https://docs.oracle.com/en/java/javase/17/gctuning/garbage-collector-implementation.html#GUID-565C3B57-DB70-4D8B-9E0C-5A7E724F6023
- JEP 374: Disable and Deprecate Biased Locking:https://openjdk.org/jeps/374
- OpenJDK/HotSpot 源码(oops/oop.hpp):https://hg.openjdk.org/jdk/jdk/file/tip/src/hotspot/share/oops/oop.hpp
本作品系原创,采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,转载请注明出处。
