内存布局
总计(byte):(m+c+f+p+l)%8=0
1、mark word->m
2、class对象指针->c
3、类字段->f
4、补齐位->p
5、如果是数组还有数组长度->l
引入依赖
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
测试案列
排序规则一
M=MarkWord
C=类型指针
I=数组长度
计算公式(M+C+I)%=0
类字段排列规则按照先基本类型,后引用类型,大的在前,小的在后,最后按声明顺序排列。从长到短排列,引用排最后: long/double --> int/float --> short/char --> byte/boolean --> Reference
关闭指针压缩
package com;
import org.openjdk.jol.info.ClassLayout;
public class TestClass {
private String str;
private long l;
private int i;
private byte b;
private short s;
public static void main(String[] args) {
TestClass testClass = new TestClass();
System.out.println(ClassLayout.parseInstance(testClass).toPrintable());
}
}
com.TestClass object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 28 30 dd 16 (00101000 00110000 11011101 00010110) (383594536)
12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
16 8 long TestClass.l 0
24 4 int TestClass.i 0
28 2 short TestClass.s 0
30 1 byte TestClass.b 0
31 1 (alignment/padding gap)
32 8 java.lang.String TestClass.str null
Instance size: 40 bytes
Space losses: 1 bytes internal + 0 bytes external = 1 bytes total
结论1
结论:由于关闭了指针压缩,所以(M+C+I)%8=0,那么字段的排序规则符合先基本类型后引用类型,大的在前,小的在后。这句话是可以证明的,但是无法证明是按声明的字段排序的,因为上面的大小都不一样。
package com;
import org.apache.lucene.util.RamUsageEstimator;
import org.openjdk.jol.info.ClassLayout;
public class TestClass {
private String str;
private long l;
private float f;
private int i;
private byte b;
private boolean blen;
private short s;
public static void main(String[] args) {
TestClass testClass = new TestClass();
System.out.println(ClassLayout.parseInstance(testClass).toPrintable());
}
}
调整位置前:
com.TestClass object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 28 30 ba 17 (00101000 00110000 10111010 00010111) (398077992)
12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
16 8 long TestClass.l 0
24 4 float TestClass.f 0.0
28 4 int TestClass.i 0
32 2 short TestClass.s 0
34 1 byte TestClass.b 0
35 1 boolean TestClass.blen false
36 4 (alignment/padding gap)
40 8 java.lang.String TestClass.str null
Instance size: 48 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total
调整位置后:
com.TestClass object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 28 30 67 17 (00101000 00110000 01100111 00010111) (392638504)
12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
16 8 long TestClass.l 0
24 4 int TestClass.i 0
28 4 float TestClass.f 0.0
32 2 short TestClass.s 0
34 1 boolean TestClass.blen false
35 1 byte TestClass.b 0
36 4 (alignment/padding gap)
40 8 java.lang.String TestClass.str null
Instance size: 48 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total
细细观察4个字节的和一个字节。
结论2
字段输出的顺序也是和声明字段的前后顺序是一样的,在字节大小相同的情况下。
排序规则二
计算公式(m+c+l)%8 !=0
优先从基本类型字段中找出一个 字段f,使得 (m+c+l+f) %8 =0,如64位jdk开启指针压缩的普通对象mark word+class refence = 12,如果类字段中有int或者float,会优先把这个字段排在前面 ,如果有多个的话,只会选择排在最前列的那个字段,其余字段按照规则一排列;如果没有int或者float,会根据大小的顺序选择 short char byte boolean,选择一个或多个字段大小和为4byte排列,如果只有一个上述字段,那就只排列一个,然后补空位到4byte。
开启指针压缩:
package com;
import org.apache.lucene.util.RamUsageEstimator;
import org.openjdk.jol.info.ClassLayout;
public class TestClass {
private double a1;
private short a2;
private float a3;
private int a4;
private byte a5;
private char a6;
private long a7;
private boolean a8;
public static void main(String[] args) {
TestClass testClass = new TestClass();
System.out.println(ClassLayout.parseInstance(testClass).toPrintable());
}
}
执行结果:
com.TestClass object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 05 c1 00 20 (00000101 11000001 00000000 00100000) (536920325)
12 4 float TestClass.a3 0.0
16 8 double TestClass.a1 0.0
24 8 long TestClass.a7 0
32 4 int TestClass.a4 0
36 2 short TestClass.a2 0
38 2 char TestClass.a6
40 1 byte TestClass.a5 0
41 1 boolean TestClass.a8 false
42 6 (loss due to the next object alignment)
Instance size: 48 bytes
Space losses: 0 bytes internal + 6 bytes external = 6 bytes total
结论
由于开启了指针压缩这个类也没有数组所以(M+C+I)%8!=0,由于需要对齐,还缺少4个字节,由于float和int都是4个字节,但是排序规则是按照声明顺序的,所以是(M+C+I+F(float))=0,剩下的就按照排序规则进行排序了。