java内存对齐_Java对象内存布局对齐填充等价形式推导

在《Java对象的内存布局》中给出了32位HotSpot虚拟机和64位HotSpot虚拟机下Java对象内存布局的对齐填充规则,为了便于在“基于Java对象内存布局计算Java对象大小的算法”中应用这些对齐填充规则,本文尝试推导这些对齐填充规则的等价形式。

本文结构分为两个部分:1)一条定理;2)分32位HotSpot虚拟机和64位HotSpot虚拟机分别进行推导。

备注:

以“Ak”表示“k-对齐”操作符。

一、一条定理

假如有:

1

2

3

4A+B%M=0

A+C+D%M=0

0<=B

0<=C+D

那么:

1B=C+D

二、推导

2.1、32位HotSpot虚拟机

从《Java对象的内存布局》中复制相应的对齐填充规则,如下所示:

1

2

3

4

5

6规则1:8种原生基本类型或者对象引用类型字段内存起始地址需满足“相应类型占据字节数-对齐”,比如“int”类型字段的内存起始地址需满足“4-对齐”,“reference”类型字段的内存起始地址需满足“4-对齐”

规则2:同一类中所有字段按照以下字段类型顺序排列分配内存,字段类型顺序为“long/double,int/float,char/short,boolean/byte,reference”

规则3:父类中所有字段排列于子类中所有字段之前

规则4:假定父类中存在至少一个字段,那么子类中首字段内存起始地址需满足“4-对齐”。并且如果此时子类中含有“long类型或者double类型”字段,而且子类中首字段内存起始地址只满足“4-对齐”,而不满足“8-对齐”,那么需要“两步走”(第一步,先从以“int/float,char/short,boolean/byte,对象引用类型”顺序排列的字段队列中选取一段“以队列起点为起点的子队列”,使得这段子队列对应的所有字段相应大小累加和在小于等于4的前提下,取到最大值为止;第二步,再遵循“规则2”排列剩余字段);否则,子类中字段继续遵循“规则2”

规则5:如果是“数组对象”,那么具体元素队列中第一个元素的内存起始地址需满足“4-对齐”或者“8-对齐”(如果数组元素类型为“long类型或者double类型”,那么需满足“8-对齐”;否则,需满足“4-对齐”)

规则6:如有必要需进行字节填充,以使得接下来毗邻的Java对象内存起始地址满足“8-对齐”

2.1.1、等价规则1

2.1.1.1、规则描述

在计算“一般实例对象obj”自身大小时,如果不考虑祖先类中字段,那么计算过程可描述为:

1obj自身大小=A8(MarkWord+类型指针+obj相应类所有字段相应大小累加和)

2.1.1.2、推导

根据“规则1,规则2和规则6”可知,计算区域主要分为3个部分:“MarkWord+类型指针,以A表示该区域字节大小”,“所有8种原生基本类型字段,以B表示该区域字节大小”和“所有对象引用类型字段,以C表示该区域字节大小”。分别以“AB,BC,CC”表示相应可能需要填充的区域。如图1所示。

图1

938b7528284ea7a38001dd89af48f3a3.png

现在即需要证明D=AB+BC+CC,其中“D”表示执行上述“A8”操作时需要填充的最小字节大小。

证明步骤如下:

现有A+AB+B+BC+C+CC%8=0和A+B+C+D%8=0

由于A=4+4=8,因此,AB=0

由于对象引用类型字节大小为4字节,因此,0<=BC<4,且CC=0或者4,那么BC+CC<8

根据上述内容,可知0<=AB+BC+CC<8,而根据定义,D也满足0<=D<8,应用“一、一条定理”中的定理,AB+BC+CC=D得证

2.1.2、等价规则2

2.1.2.1、规则描述

在计算“一般实例对象obj”自身大小时,如果考虑祖先类中字段,那么计算过程可描述为:

1

2

3obj自身大小=A8(MarkWord+类型指针+PR(obj对应类的父类PObj)+obj对应类中所有字段相应大小累加和)

不满足“PR(PObj的父类PPObj)%8!=0 && PObj类中存在且只存在long类型或者double类型字段”:PR(obj对应的父类PObj)=A4(PR(PObj的父类PPObj)+PObj类中所有字段相应大小累加和)

满足“PR(PObj的父类PPObj)%8!=0 && PObj类中存在且只存在long类型或者double类型字段”:PR(obj对应的父类PObj)=A4(PR(PObj的父类PPObj)+4+PObj类中所有字段相应大小累加和)[这里的A4是多余的]

2.1.2.2、推导

根据“规则1,规则2,规则3,规则4和规则6”,可得以下三个计算模型。

1、计算模型1

对应“等式1”,计算区域主要分为:“MarkWord+类型指针,以A表示该区域字节大小”,“所有祖先类字段,以B表示该区域字节大小”,“本类中被提前置于B之后的字段集合,以C2表示该区域字节大小,根据‘规则4’,C2中不可能‘既包含8种原生基本类型,又包含对象引用类型’”,“本类中long或者double类型字段集合,以C1表示该区域字节大小”,“本类中除了C1和C2之外的原生基本类型字段集合,以C3表示该区域字节大小”和“本类中除了C1和C2之外的对象引用类型字段集合,以C4表示该区域字节大小”。分别以“AB,BC,CC,CD”表示相应可能需要填充的区域。如图2所示。

图2

6e427490fa39c024987932deb9410a65.png

现在即需要证明D=AB+BC+CC+CD,其中“D”表示执行上述“A8”操作时需要填充的最小字节大小。

证明步骤如下:

现有A+AB+B+C2+BC+C1+C3+CC+C4+CD%8=0和A+B+C2+C1+C3+C4+D%8=0

由于A=4+4=8,因此,AB=0

根据“规则4”,得0<=BC<=4

对象引用类型字节大小为4,故有0<=CC<4,CD=0或者CD=4

当BC=0时,有0<=CC+CD<8;当BC=4时,CC=0且CD=0;当0

根据上述内容,可知0<=AB+BC+CC+CD<8,而根据定义,D也满足0<=D<8,应用“一、一条定理”中的定理,AB+BC+CC+CD=D得证

2、计算模型2

对应“等式2”,计算区域主要分为:“本父类的所有祖先类字段,以PA表示该区域字节大小”,“本父类中被提前置于PA之后的字段集合,以PC2表示该区域字节大小”,“本父类中long或者double类型字段集合,以PC1表示该区域字节大小”,“本父类中除了PC1和PC2之外的原生基本类型字段集合,以PC3表示该区域字节大小”和“本父类中除了PC1和PC2之外的对象引用类型字段集合,以PC4表示该区域字节大小”。分别以“AC,CC和CD”来表示相应可能需要填充的区域。如图3所示。

图3

c4b33f259f66d21fecee41b4eb61e659.png

现在即需要证明D=AC+CC+CD,其中“D”表示执行上述“A4”操作时需要填充的最小字节大小。

证明步骤如下:

现有PA+PC2+AC+PC1+PC3+CC+PC4+CD%4=0和PA+PC2+PC1+PC3+PC4+D%4=0

根据“规则4”,得0<=AC<=4,且由于不满足“PR(PObj的父类PPObj)%8!=0 && PObj类中存在且只存在long类型或者double类型字段”,因此0<=AC<4

对象引用类型字节大小为4,因此,CD=0

可很容易推得:有0<=CC<4。当0

根据上述内容,可知0<=AC+CC+CD<4,而根据定义,D也满足0<=D<4,应用“一、一条定理”中的定理,AC+CC+CD=D得证

3、计算模型3

对应“等式3”,可根据“规则1,规则2,规则3,规则4和规则6”直接推得。

2.1.3、等价规则3

2.1.3.1、规则描述

在计算“数组对象obj”自身大小时,那么计算过程可描述为:

1obj自身大小=A8(MarkWord+类型指针+数组长度记录区域+数组长度*数组元素类型字节大小)

2.1.3.2、推导

根据“规则5和规则6”可知,计算区域主要分为两个部分:“MarkWord+类型指针+数组长度记录区域,以A表示该区域字节大小”和“数组元素队列,以B表示该区域字节大小”。分别以“AB,BB”表示相应可能需要填充的区域。如图4所示。

图4

7916b8dd84dd55719b90f6082d3e20f5.png

现在即需要证明D=AB+BB,其中“D”表示执行上述“A8”操作时需要填充的最小字节大小。

证明步骤如下:

现有A+AB+B+BB%8=0和A+B+D%8=0

有A=4+4+4=12

当数组元素类型为“long”或者“double”时,AB=4,BB=0;否则,AB=0,0<=BB<8

根据上述内容,可知0<=AB+BB<8,而根据定义,D也满足0<=D<8,应用“一、一条定理”中的定理,AB+BB=D得证

2.2、64位HotSpot虚拟机

从《Java对象的内存布局》中复制相应的对齐填充规则,如下所示:

1

2

3

4

5

6规则1:8种原生基本类型或者对象引用类型字段内存起始地址需满足“相应类型占据字节数-对齐”,比如“int”类型字段的内存起始地址需满足“4-对齐”,“reference”类型字段的内存起始地址需满足“8-对齐”

规则2:同一类中所有字段按照以下字段类型顺序排列分配内存,字段类型顺序为“long/double,int/float,char/short,boolean/byte,reference”

规则3:父类中所有字段排列于子类中所有字段之前

规则4:假定父类中存在至少一个字段,那么子类中首字段内存起始地址需满足“8-对齐”

规则5:如果是“数组对象”,那么具体元素队列中第一个元素的内存起始地址需满足“8-对齐”

规则6:如有必要需进行字节填充,以使得接下来毗邻的Java对象内存起始地址满足“8-对齐”

2.2.1、等价规则1

2.2.1.1、规则描述

在计算“一般实例对象obj”自身大小时,如果不考虑祖先类中字段,那么计算过程可描述为:

1obj自身大小=A8(MarkWord+类型指针+obj相应类所有字段相应大小累加和)

2.2.1.2、推导

根据“规则1,规则2和规则6”可知,计算区域主要分为3个部分:“MarkWord+类型指针,以A表示该区域字节大小”,“所有8种原生基本类型字段,以B表示该区域字节大小”和“所有对象引用类型字段,以C表示该区域字节大小”。分别以“AB,BC,CC”表示相应可能需要填充的区域。如图5所示。

图5

dfd6aa70bf37f3f9ae97fef332e3bd98.png

现在即需要证明D=AB+BC+CC,其中“D”表示执行上述“A8”操作时需要填充的最小字节大小。

证明步骤如下:

现有A+AB+B+BC+C+CC%8=0和A+B+C+D%8=0

由于A=8+8=16,因此,AB=0

由于对象引用类型字节大小为8字节,因此,0<=BC<8,且CC=0,那么BC+CC<8

根据上述内容,可知0<=AB+BC+CC<8,而根据定义,D也满足0<=D<8,应用“一、一条定理”中的定理,AB+BC+CC=D得证

2.2.2、等价规则2

2.2.2.1、规则描述

在计算“一般实例对象obj”自身大小时,如果考虑祖先类中字段,那么计算过程可描述为:

1

2obj自身大小=A8(MarkWord+类型指针+PR(obj对应类的父类PObj)+obj对应类中所有字段相应大小累加和)

PR(obj对应的父类PObj)=A8(PR(PObj的父类PPObj)+PObj类中所有字段相应大小累加和)

2.2.2.2、推导

根据“规则1,规则2,规则3,规则4和规则6”,可得以下两个计算模型。

1、计算模型1

对应“等式1”,计算区域主要分为:“MarkWord+类型指针,以A表示该区域字节大小”,“所有祖先类字段,以B表示该区域字节大小”,“本类中8种原生基本类型字段集合,以C表示该区域字节大小”和“本类中对象引用类型字段集合,以D表示该区域字节大小”。分别以“AB,BC,CD,DD”表示相应可能需要填充的区域。如图6所示。

图6

e416422d5505d88c7e2d392aacbc999d.png

现在即需要证明E=AB+BC+CD+DD,其中“E”表示执行上述“A8”操作时需要填充的最小字节大小。

证明步骤如下:

现有A+AB+B+BC+C+CD+D+DD%8=0和A+B+C+D+E%8=0

由于A=8+8=16,因此,AB=0

B区域一定满足“8-对齐”,因此,BC=0

对象引用类型字节大小为8,故而有0<=CD<8,DD=0

根据上述内容,可知0<=AB+BC+CD+DD<8,而根据定义,E也满足0<=E<8,应用“一、一条定理”中的定理,AB+BC+CD+DD=E得证

2、计算模型2

对应“等式2”,计算区域主要分为:“本父类的所有祖先类字段,以PA表示该区域字节大小”,“本父类中原生基本类型字段集合,以PB表示该区域字节大小”和“本父类中对象引用类型字段集合,以PC表示该区域字节大小”。分别以“AB,BC和CC”表示相应可能需要填充的区域。如图7所示。

图7

4602883b63033917f07abb66d40b61bc.png

现在即需要证明D=AB+BC+CC,其中“D”表示执行上述“A8”操作时需要填充的最小字节大小。

证明步骤如下:

现有PA+AB+PB+BC+PC+CC%8=0和PA+PB+PC+D%8=0

PA区域一定满足“8-对齐”,因此,AB=0

对象引用类型字节大小为8,故而有0<=BC<8,且CC=0

根据上述内容,可知0<=AB+BC+CC<8,而根据定义,D也满足0<=D<8,应用“一、一条定理”中的定理,AB+BC+CC=D得证

2.2.3、等价规则3

2.2.3.1、规则描述

在计算“数组对象obj”自身大小时,计算过程可描述为:

1obj自身大小=A8(MarkWord+类型指针+数组长度记录区域+4+数组长度*数组元素类型字节大小)

2.2.3.2、推导

根据“规则5和规则6”,直接可推得。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值