Java对象中实例数据发生的间隙填充alignment/padding gap条件是什么?

1: alignment/padding gap是什么?

先看一张图:
在这里插入图片描述
对象分四部分:
圈住的第一部分包括:8字节的makedown+4字节的类型指针
圈住的第二部分是实例数据
圈住的第三部分是8字节对齐,padding
如果这些知识不清楚的话没必要往下看了,今天我们要说的是示例数据中出现alignment/padding gap的条件是什么?

2: 验证什么条件下会出现alignment/padding gap

问了一些人:给出的答案是:当实例数据加起来的字节数不是4的倍数的时候会触发alignment/padding gap,我只能说,经我证明,这句话是错误的.
如下图:
在这里插入图片描述
那么,真正的原因是什么,其实我也不清楚,我都是靠猜测+验证.我猜测:如果实例数据只是基本数据类型,那是不会触发alignment/padding gap的,必须要有至少一个非基本数据类型的存在,且基本数据类型的字节数和不是4的倍数.满足这两个条件才会触发.

下面进行验证:

验证1:只有基本数据类型时,如果存在4字节的基本数据类型,或者多个小字节基本数据类型加起来够4字节,或者所有字节和加起来小于4字节,尽管不是4的倍数,也是不会触发的。 只有当字节和大于4,且小字节加起来小于4时会触发。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
2:验证二:存在至少一个非基本数据类型,但是基本类型字节和是4的倍数,也不会触发在这里插入图片描述

3;验证三:当存在非基本数据类型,且基本数据类型字节和不是4的倍数的时候会触发.
在这里插入图片描述

针对上面,间隙跳填充alignment/padding,在基本数据类型罗列完成之后开始填充.这里将属性调换顺序,再次验证.
在这里插入图片描述

3:结论

我也是猜测+自己验证的,还有其他的触发条件暂时没发现。因此:这里先总结一下已经验证的,以后发现了新的触发条件,再来完善.
结论:
1:如果都是基本数据类型,只有当不存在4字节的,或者小字节加起来填不满4字节,且所有字节和>4的时候触发。
2:如果实例数据存在非基本数据类型,也就是引用数据类型,先罗列并计算所有的基本类型数据的字节和,如果字节和不是4的倍数,那么此时会触发alignment/padding

查了一些资料,我觉得人家说的很对,看源码很重要,可惜自己是水平太差,看不懂。
这个是可以通过-XX:FieldsAllocationStyle=0/1/2来控制,有三种分配策略

取值为0时,引用在原始类型前面, 然后依次是longs/doubles、ints、shorts/chars、bytes/booleans;即基本类型->填充字段(可以没有)->引用类型

取值为1时,引用在原始类型后面,即longs/doubles、ints、shorts/chars、bytes/booleans 然后是引用类型;即引用类型->基本类型->填充字段(可以没有)

取值为2时,父类中的引用类型与子类中的引用类型放在一起,此时父类采用策略0,子类采用策略1。

取值0和取值1都是将基本数据类型按照从大到小的方式排序,这样可以降低空间开销。而取值3 将父类和子类的引用放在一起,
这样可以增加 GC 效率,试想在GC 扫描引用时,由于父类和子类的引用连续,可能只需要扫描一个内存行即可,
若父类和子类的引用不连续,则需要扫描多个内存行;另外连续的内存引用还可减少 OopMap 的个数,从而达到提高 GC 效率的目的。

细心的朋友会发现,我们上面的测试,是基本类型->填充字段(可以没有)->引用类型,也就是默认0策略。还细心的朋友会发现基本类型的排序不符合longs/doubles、ints、shorts/chars、bytes/booleans的规则啊。原因很简单,因为对象头占了12字节,还记得我们刚刚说的8字节对齐吗,这里正好可以插入一个4字节的数据,如果long类型排在前面的话,这4字节是不是就浪费了呢,所以JVM就帮我们把age(int)放到了long类型之前(可以通过-XX:+/-CompactFields进行控制,默认开启),可以通过
XX:-UseCompressedOops关闭指针压缩,XX:+UseCompressedOops开启指针压缩。

ps:想详细了解的,可以参考这个链接

最后,奉上ClassLayout工具类的pom依赖,方便大家自行测试:

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

就到这里吧,其实现在内心就一个想法:看懂源码很重要呀,翻翻源码就好了;不知道的人就很难受,以后慢慢进步吧。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值