虚拟机:Java HotSpot(TM) 64-Bit Server VM (25.221-b11, mixed mode)

  对象的内存以字节为单位,必须是8的倍数,它的构成由3部分组成:对象头+实例数据+对齐内存。对象头主要包括对象的运行行元数据,比较哈希码、GC分代年龄、锁状态标志还有类型指针,类型指针指向类元数据,表明该对象所属类型。实例数据包括自身数据和所有父级数据,所有父级占内存大小都是8的倍数,没有就需要补齐。类型指针一般为4字节,在关闭压缩普通对象指针时(-XX:+UseCompressedOops)为8字节,UseCompressedOops默认是开启的,只有虚拟机内存达到32G以上,4个字节已经无法满足寻址需求时,才需要关闭该参数。

  普通对象头除类型指针外的大小为8字节,在开启压缩总大小为12字节,不开启压缩总大小为16字节;数组对象头在开启压缩时是16字节,不开启压缩为24字节。

  各种类型大小如下:

对象类型 字节  
boolean 1  
byte 1  
short 2  
char 2  
int 4  
float 4  
long 8  
double 8  
引用类型 开启指针压缩为4,不开启为8  
普通对象头 开启指针压缩为12,不开启为8  
数据对象头 开启指针压缩为16,不开启为24  

例1:

public class Persion {
    int id;
}

开启压缩普通对象指针时,对象大小:(8+4)+4+0=16字节,补齐0字节

关闭压缩普通对象指针时,对象大小:(8+8)+4+4=24字节,补齐4字节

 

例2:

public class Persion {
    int id;
    String name;
    int age;
    Date birthday;
}

开启压缩普通对象指针时,对象大小:(8+4)+(4+4+4+4)+4=32字节,补齐了4字节。

关闭压缩普通对象指针时,对象大小:(8+8)+(4+8+4+8)+0=40字节,补齐了0字节

例3:

public class Persion {
    int id;
    String name;
    int age;
    Date birthday;
    boolean school;
}

public class Student extends Persion {
    int b;
}

开启压缩普通对象指针时:

Person对象的大小为:(8+4)+(4+4+4+4+1)+7=32字节,补齐了7字节。

Student对象的大小为:(8+4)+(4+(4+4+4+4+1+7)) +0=40字节,Person对象补齐了7字节。

关闭压缩普通对象指针时:

Person对象的大小为:(8+8)+(4+8+4+8+1)+7=48字节,补齐7字节

Student对象的大小为:(8+8)+(4+(4+8+4+8+1+7))+4=56字节,Person对象补齐了7字节,Student补齐4字节。

例4:

class MyList {
    Persion[] elementData = new Persion[10];
}

开启压缩普通对象指针时:

MyList对象大小:(8+4)+4+0=16字节,补齐了0字节

new Person[10]数组对象大小:16+4*10+0=56字节,补齐了0字节

关闭压缩普通对象指针时:

MyList对象大小:(8+8)+8+0=24字节,补齐了0字节

new Person[10]数组对象大小:24+8*10+0=104字节,补齐了0字节

例5:

@SuppressWarnings("serial")
class MyArrayList extends ArrayList<Persion> {

}

AarryList和它父级只有3个非静态成员变量(size为整数、elementData为数组引用,在ArrayList类中,modCount为整数在AbstractList类中),静态变量内存在堆的另外部分,不在对象内。

开启压缩普通对象指针时:

MyArrayList对象大小:(8+4)+(0+(4+4+(4+4)))+4=32字节,AbstractList做了一次补齐,整体做了一次补齐。(与下图结果不符,后面抽时间在看看

关闭压缩普通对象指针时:

MyArrayList对象大小:(8+8)+(0+(4+8+(4+4)+4))+0=40字节,AbstractList做了一次补齐,ArrayList做了一次补齐

 

posted on 2019-09-26 11:18  玄同太子  阅读(7709)  评论(5编辑  收藏  举报