JAVA字节对齐详解

JAVA字节对齐

一般而言,Java对象不需要考虑字节对齐,JVM编译时会自动优化。但C/C++/C#等需要考虑对象次序,避免空间浪费。(注:本文中使用的jdk版本是1.8为基础的 。)

对象结构

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

对象头
  • Mark Word:包含一系列的标记位,比如轻量级锁的标记位,偏向锁标记位等等。在32位系统占4字节,在64位系统中占8字节;
  • Class Pointer(类型指针):用来指向对象对应的Class对象(其对应的元数据对象)的内存地址。在32位系统占4字节,在64位系统中占8字节;
  • Length:如果是数组对象,还有一个保存数组长度的空间,占4个字节;
实例数据

八种基础数据类型及相关引用类型

  • byte、boolean是1个字节
  • short、char是2个字节
  • int、float是4个字节
  • long、double是8个字节
  • reference是4个字节

对齐方式

64位HotSpot VM每次读取数据的最小单位是8字节,因此对象大小必须保持8字节的整数倍,不足则填充。

关于编码(对比C/C++)

在C/C++中,结构体中不合理属性顺序,会增加对象所需的存储空间。

测试代码

struct Person1 {
    char _char;
    int _int;
    short _short;
};

struct Person2 {
    char _char;
    short _short;
    int _int;
};



int main() {
    printf("_person1 sizeof: %d \n", sizeof(Person1));
    printf("_person2 sizeof: %d \n", sizeof(Person2));
}

结果

_person1 sizeof: 12 
_person2 sizeof: 8 

因此,在C/C++编码过程中,合理安排结构体属性的次序是很有必要的。幸运的是JVM会自动调整属性的次序。保证对象所需的存储空间最小。
测试代码

public class Person {
    public byte _1_byte;
    public int _1_int;
    public boolean _boolean;
    public int _2_int;
    public short _short;
    public double _double;
    public char _char;
    public long _long;
    public byte _2_byte;
    // 引用类型
    public Person2 person2;
}

public class Person2 {
    public byte _byte;
    public boolean _boolean;
    public char _char;
    public short _short;
    public int _int;
    public long _long;
    public float _float;
    public double _double;
}

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

结果

OFF  SZ                               TYPE DESCRIPTION               VALUE
  0   8                                    (object header: mark)     0x0000000000000001 (non-biasable; age: 0)
  8   4                                    (object header: class)    0xf800c392
 12   4                                int Person._1_int             0
 16   8                             double Person._double            0.0
 24   8                               long Person._long              0
 32   4                                int Person._2_int             0
 36   2                              short Person._short             0
 38   2                               char Person._char               
 40   1                               byte Person._1_byte            0
 41   1                            boolean Person._boolean           false
 42   1                               byte Person._2_byte            0
 43   1                                    (alignment/padding gap)   
 44   4   com.yejing.exercise.bean.Person2 Person.person2            null
Instance size: 48 bytes
Space losses: 1 bytes internal + 0 bytes external = 1 bytes total

可以看出 “_1_byte” 属性的次序被自动调整到靠下的地方,使得小对象相邻,减少空白填充。
另外,经过多组测试,发现JVM在字节对齐的过程中相同大小的对象会按之前的属性次序存储。如 long, double; int,float; byte,boolean。

其他

https://www.163.com/dy/article/G7BGCH720517O4DT.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值