您的位置 首页 java

Java对象背后的故事(中)

在上篇文章中介绍一个对象的组成部分主要分为三部分。对象头、实例数据、填充对齐。实例数据。这里我们就继续分析这三部分中具体的组成情况。

为了证实一个对象存在这3个部分。这里 使用 JOL( java object layout 是分析 JVM 中对象布局的工具,该工具大量使用了 Unsafe、JVMTI 来解码布局情况)来分析。这里使用0.16版本。目前市面的电脑绝大多数多是64位操作系统,这里也基于64位操作系统来展开讲解,32位的大家知道就可以了。本人电脑操作系统 MacOS Monterey 12.2.1。

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

Hotspot 虚拟机文档 “oops/oop.hp” 有对 Markword 字段的定义

 Bit-format of an object header (most significant first, big endian layout below):


32 bits:
--------
hash:25 ------------>| age:4    biased_ lock :1 lock:2 (normal object)
 Java Thread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)
size:32 ------------------------------------------>| (CMS free block)
PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)


 64 bits:
--------
unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)
JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)
PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
size:64 ----------------------------------------------------->| (CMS free block)


unused:25 hash:31 -->| cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && normal object)
JavaThread*:54 epoch:2 cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && biased object)
narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)  

理论上一个空对象的大小为对象头大小12字节(Markword 8字节、class pointer 4字节),考虑到8 字节对齐 填充,需要补齐4字节为8 的2倍16字节。

我们来new一个空对象

 public class AnalysisObject {
}  

使用JOL分析AnalysisObject对象信息

     public  static   void  main(String[] args) {
       AnalysisObject object = new AnalysisObject();
        System.out.println(ClassLayout.parseInstance(object).toPrintable());
    }  

输出结果信息

 com.github.sylphlike.web.AnalysisObject object internals:
OFF  SZ   TYPE DESCRIPTION               VALUE
  0   8        (object header: mark)     0x000000000000000d (biasable; age: 1)
  8   4        (object header: class)    0x00066a48
 12   4        (object alignment gap)    
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total  

表头依次为 OFF:在内存中的起始位置 SZ:占用大小(字节)TYPE DESCRIPTION: 类型 VALUE:具体值

(object header: mark) 对应MarkWord,占用大小8 byte

(object header: class) 对应 class pointer 占用大小4byte

(object alignment gap) 对应 Padding 占用大小为4

Instance size 对象占用的总字节数大小

Space losses 对应对齐填充大小

接下来我们给对象添加一下属性方法。

 public class AnalysisObject {
     private  String s;
    private int i;
    private boolean b;
    private double d;
    private Integer in;
    public void method(){}
}  

输出结果信息

 com.github.sylphlike.web.AnalysisObject object internals:
OFF  SZ                TYPE DESCRIPTION               VALUE
  0   8                     (object header: mark)     0x000000000000000d (biasable; age: 1)
  8   4                     (object header: class)    0x00066a48
 12   4                 int AnalysisObject.i          0
 16   8              double AnalysisObject.d          0.0
 24   1              boolean  AnalysisObject.b          false
 25   3                     (alignment/padding gap)   
 28   4    java.lang.String AnalysisObject.s          null
 32   4   java.lang.Integer AnalysisObject.in         null
 36   4                     (object alignment gap)    
Instance size: 40 bytes
Space losses: 3 bytes internal + 4 bytes external = 7 bytes total  

从结果中看出对象占用40字节大小。Instance size: 40 bytes. 一共5个属性,一个方法。int占4字节、boolean占1字节、double占8字节、 Integer String 为引用类型所以占4字节。

从上面结果中我们还发现有两种填充方式 3 bytes internal 和 4 bytes external. 为什么存在两种填充方式?这里先给出结论。后面再探讨该问题;出现(alignment/padding gap)有以下两种情况

1、如果都是基本数据类型,只有当不存在4字节的,或者小字节加起来填不满4字节,且所有字节和大于4的时候触发alignment/padding

2、如果实例数据存在非基本数据类型,也就是引用数据类型,先罗列并计算所有的基本类型数据的字节和,如果字节和不是4的倍数,那么此时会触发alignment/padding。

Markword中存放的数据在对象的整个 生命周期 内都是非常关键的,放在后后一篇文章中单独来阐述。

文章来源:智云一二三科技

文章标题:Java对象背后的故事(中)

文章地址:https://www.zhihuclub.com/183189.shtml

关于作者: 智云科技

热门文章

网站地图