Java对象在内存中的布局 没有你想的那么神秘

本文详细探讨了Java对象在内存中的布局,包括对象头的Mark Word结构,存储哈希码、GC信息等。还介绍了实例数据和对齐填充,并通过JOL工具展示了对象头的查看方法。同时,文章讨论了Java对象在不同锁状态(偏向锁、轻量级锁、重量级锁)下的变化,帮助理解JVM的锁优化机制。
摘要由CSDN通过智能技术生成

写在前面

Java是用C++写的,所以java对象最终会映射到c++中的某个对象,用这个对象可以描述所有Java对象。而我们所熟知的synchronized锁的优化就是基于这个对象来实现的。

对象在内存中的布局

Java对象在被创建的时候,在内存分配完成后,虚拟机需要对对象进行必要设置, 例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。

这些信息存放在对象的对象头(Object Header)中。根据虚拟机当前运行状态的不同,如是否启用偏向锁等对象头会有不同的设置方式。

在虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)

对象头

HotSpot虚拟机对象头包括两部分信息,第一部分用于存储对象自身的运行时数据,如哈希码、GC分代年、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳。

这部分数据的长度在32位和64位的虚拟机中分别是32bit和64bit,官方称为"Mark Word"。 考虑到虚拟机的空间效率,Mark Word被设计成一个非固定的数据结构以便在极小的空间内存储尽量多的信息。

对象头另一部分是类型指针,即指向对象的类元数据,虚拟机通过这个指针确定该对象是哪个类的实例。

我们可以在JVM源码(hotspot/share/oops/markOop.hpp)中看到对象头中存储内容的定义

class markOopDesc: public oopDesc {
   
 public:
  enum {
    age_bits             = 4,
         lock_bits            = 2,
         biased_lock_bits     = 1,
         max_hash_bits        = BitsPerWord - age_bits - lock_bits - biased_lock_bits,
         hash_bits            = max_hash_bits > 31 ? 31 : max_hash_bits,
         cms_bits             = LP64_ONLY(1) NOT_LP64(0),
         epoch_bits           = 2
  };
}

对象头

  • hash: 对象的哈希码
  • age: 对象的分代年龄
  • biased_lock : 偏向锁标识位
  • lock: 锁状态标识位
  • JavaThread* : 持有偏向锁的线程ID
  • epoch: 偏向时间戳

例如在32位的HotSpot虚拟机中,如果对象处于未被锁定的状态下,那么Mark Word的32bit空间的25bit用于存储对象哈希码,4bit用于存储对象分代年龄,2bit用于存储锁标志位,1bit固定为0
而在其他状态(轻量级锁,重量级锁,GC标记,可偏向)下对象的存储内容如下表所示

32位系统

实例数据

实例数据部分是对象真正存储的有效信息,也是在程序代码中说定义的各种类型的字段内容。

对其填充

第三部分对其填充并不是必然存在的,也没有特别的含义,仅是占位符的作用,因为HotSpot VM的内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,就是对象的大小必须是8字节的整数倍。而对象头部分正好是8字节的倍数,因此当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。

查看对象头

我们可以通过openjdk的jol工具来查看对象头存储的内容,首先代码如下

<dependency>
  <groupId>org.openjdk.jol</groupId>
  <artifactId>jol-core</artifactId>
  <version>0.9</version>
</dependency>

public class GetRange {
   
  // -XX:-UseCompressedOops
  public 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值