美文网首页
JVM-3:Java对象存储

JVM-3:Java对象存储

作者: 厨房里的工程师 | 来源:发表于2018-06-10 14:29 被阅读0次

一个Java对象可以分为三部分存储在内存中,分别是:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。

1. 对象头

在HotSpot虚拟机中,对象头可以分为两部分。

1.1 对象自身的运行时数据

这部分存储包括哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。这部分数据被官方称为Mark Word,在32位和64位的虚拟机中的大小分别为32bit和64bit。

由于对象头信息是与对象自身定义的数据无关的额外存储成本,考虑到虚拟机的空间效率,Mark Word被设计成一个非固定的数据结构以提高存储空间的利用率。即这部分数据会根据对象的状态来分配存储空间。以下是一个64位虚拟机中的例子(引用链接):

|----------------------------------------------------------------------------------------|--------------------|
|                                    Object Header (64 bits)                             |        State       |
|-------------------------------------------------------|--------------------------------|--------------------|
|                  Mark Word (32 bits)                  |      Klass Word (32 bits)      |                    |
|-------------------------------------------------------|--------------------------------|--------------------|
| identity_hashcode:25 | age:4 | biased_lock:1 | lock:2 |      OOP to metadata object    |       Normal       |
|-------------------------------------------------------|--------------------------------|--------------------|
|  thread:23 | epoch:2 | age:4 | biased_lock:1 | lock:2 |      OOP to metadata object    |       Biased       |
|-------------------------------------------------------|--------------------------------|--------------------|
|               ptr_to_lock_record:30          | lock:2 |      OOP to metadata object    | Lightweight Locked |
|-------------------------------------------------------|--------------------------------|--------------------|
|               ptr_to_heavyweight_monitor:30  | lock:2 |      OOP to metadata object    | Heavyweight Locked |
|-------------------------------------------------------|--------------------------------|--------------------|
|                                              | lock:2 |      OOP to metadata object    |    Marked for GC   |
|-------------------------------------------------------|--------------------------------|--------------------|

1.2 对象的类型指针

即指向对象的类元数据的指针。虚拟机可以通过该指针判定对象实例属于哪个类。

在Java对象中比较特殊的是Java数组,一个数组实例的对象头中必须记录数组的长度。JVM可以通过对象头中的数组长度数据来判定数组的大小,这是访问数组类型的元数据无法得到的。

2. 对象的实例数据

前面提到对象头是对象的额外开销,只有实例数据才是一个对象实例存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。这部分内容同时记录了子类从父类继承所得的各类型数据。

3. 填充

对齐填充在对象数据中并不是必然的,只是起着占位符的作用,没有特别含义。HotSpot要求对象起始地址必须是8字节的整数倍。对象头的大小刚好符合要求,因此当实例数据没有对齐时,就需要通过填充来对齐数据。

4. 获取类的元数据

虚拟机在加载类的时候会将类的信息、常量、静态变量和即时编译器编译后的代码等数据存储在方法区(Method Area)。类的元数据,即类的数据描述,也被存在方法区。我们知道对象头中会存有对象的类型指针,通过类型指针可以获取类的元数据。因此,对象的类型指针其实指向的是方法区的某个存有类信息的地址。

但是,并不是每个对象实例都存有对象的类型指针。根据对象访问定位方法的不同,对象的类型指针被存放在不同的区域。

  • 通过句柄访问对象
    • 对象的类型指针被存放在句柄池中;
  • 通过Reference指针直接访问对象
    • 对象的类型指针被存放在对象本身的数据中。

5. 总结

因此,Java的对象数据存储可以理解为:

  • 引用类型(指向对象的Reference)
    • 存储在栈中
  • 对象的类的元数据 (Class MetaData)
    • 存储在方法区中
  • 对象的实例数据
    • 存储在堆中

6. 参考

相关文章

  • JVM-3:Java对象存储

    一个Java对象可以分为三部分存储在内存中,分别是:对象头(Header)、实例数据(Instance Data)...

  • Synchronize的实现原理

    1 Java对象头信息 Java对象在JVM中的结构如下: java对象包括: Mark Word(存储对象的ha...

  • JVM深度理解(一):一个对象到底有多大

    java对象内存模型 对象头:Instance Header,存储了Java对象hash、GC年龄、锁标记、cla...

  • ThreadLocal的简单了解

    存储结构Thread对象中会存储属性java.lang.Thread.threadLocals,它的类型是java...

  • 2018-04-17

    Java集合 ★★★★★集合框架:用于存储数据的容器。 特点: 1:对象封装数据,对象多了也需要存储。集合用于存储...

  • Java基础篇

    堆栈 栈 存储局部变量 存储方法调用 堆 存储Java对象(成员变量 局部变量 类变量 ->指向的对象都存储在堆内...

  • Java第三天 - 草稿

    为什么会出现集合类: Java是面向对象编程语言,为了方便对多个对象进行操作,就必须存储多个对象。因此存储多个对象...

  • Java第三天

    为什么会出现集合类: Java是面向对象编程语言,为了方便对多个对象进行操作,就必须存储多个对象。因此存储多个对象...

  • 总结-3-java

    Java: 1、java对象头: 如果对象是数组类型,则虚拟机用3个Word(字宽)存储对象头。 如果对象是非数组...

  • Java集合的分类有哪些?

    Java集合是什么?Java中的集合就像一个容器,专门用来存储Java对象(实际上是对象的引用,但习惯上称为对象)...

网友评论

      本文标题:JVM-3:Java对象存储

      本文链接:https://www.haomeiwen.com/subject/mqxfeftx.html