JVM 中 java 对象布局

java

HostSpot 虚拟机对象布局

1.java 对象布局

Java对象分为:对象头、实例数据、对齐填充组合。

对齐填充:

对齐填充并不是必然存在的,也没有特定的含义,仅仅起着占位符的作用。由于HotSpot虚拟机的自动内存管理系统要求对象的起始地址必须是8字节的整数倍,也就是对象的大小必须是8字节的整数倍。而对象头部分正好是8字节的倍数(1倍或者2倍),因此,当对象实例数据部分没有对齐的时候,就需要通过对齐填充来补全。对象字节数/8的倍数,如果不足的话 实现填充。例如:一个对象21个字节,则需要补充3个字节。

实例数据:对象中定义的成员属性。

对象头:

固定的大小。32位系统对象头大小为8个字节、64位系统对象头大小为16个字节。

HotSpot虚拟机的对象头(Object Header)包括两部分信息:

第一部分"Mark Word":用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等.

第二部分"Klass Pointer":对象指向它的类的元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。(数组,对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是从数组的元数据中无法确定数组的大小。 )

注意:在64位的虚拟机情况下 mark word 占用64位 ,32位虚拟机占32位。

64位等于多少 /8 8个字节

虚拟机源码中查看Mark Word:

 KClass Pointer:

这一部分用于存储对象的类型指针,该指针指向它的类元数据,jvm通过这个指针确定对象是哪个类的实例。该指针的位长度为JVM的一个字大小,即32位的JVM为32位,64位的JVM为64位。

如果应用的对象过多,使用64位的指针将浪费大量内存,统计而言,64的JVM将会比32位的JVM多耗费50的内存。为了节约内存可以使用选项 -XX:+UseCompressedOops 开启指针压缩。其中 oop即ordinary object pointer 普通对象指针。

如果在64位操作系统下,如果对象头字节为12个字节,说明是java虚拟机对对象头进行了压缩。

对象头压缩设置:

-XX:+UseCompressedOops 开启指针压缩

-XX:-UseCompressedOops  不开启指针压缩

对象头:Mark Word+Klass Pointer类型指针 未开启压缩的情况下

32位 Mark Word =4bytes ,类型指针 4bytes ,对象头=8bytes =64bits

64位 Mark Word =8bytes ,类型指针 8bytes ,对象头=16bytes=128bits;

注意:默认情况下,开启了指针压缩 可能只有12字节。

new出一个对象对象头占多少个字节:

如果是32位操作系统对象头占8个字节,如果是64位操作系统对象头占16个字节(没有被压缩的情况下)。

占用字节=对象头+实例数据+对齐填充/8

java 打印对象头信息所需Maven依赖:

        <dependency>

<groupId>org.openjdk.jol</groupId>

<artifactId>jol-core</artifactId>

<version>0.10</version>

</dependency>

java 代码实现:对象为 int 类型

public class UserEntity {

private int a;

public static void main(String[] args) {

UserEntity userEntity = new UserEntity();

// 打印对象头信息

System.out.println(ClassLayout.parseInstance(userEntity).toPrintable());

}

}

控制台打印结果:

com.example.test.UserEntity 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) 80 30 d1 1b (10000000 00110000 11010001 00011011) (466694272)

12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)

16 4 int UserEntity.a 0

20 4 (loss due to the next object alignment)

Instance size: 24 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java 代码实现:对象为 Interger 类型

public class UserEntity {

private Integer a;

public static void main(String[] args) {

UserEntity userEntity = new UserEntity();

// 打印对象头信息

System.out.println(ClassLayout.parseInstance(userEntity).toPrintable());

}

}

控制台打印结果:

com.example.test.UserEntity 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) 80 30 1c 1c (10000000 00110000 00011100 00011100) (471609472)

12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)

16 8 java.lang.Integer UserEntity.a null

Instance size: 24 bytes

Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

 Integer包装类型会对int类型自动的进行填充,由4变成了8,能够被8整除。

 打印 对象hashcode位置:

public class UserEntity {

private int a;

public static void main(String[] args) {

UserEntity userEntity = new UserEntity();

// 打印 hashCode 所在位置

System.out.println(Integer.toHexString(userEntity.hashCode()));

// 打印对象头信息

System.out.println(ClassLayout.parseInstance(userEntity).toPrintable());

}

}

控制台输出:

5b2133b1

com.example.test.UserEntity object internals:

OFFSET SIZE TYPE DESCRIPTION VALUE

0 4 (object header) 01 b1 33 21 (00000001 10110001 00110011 00100001) (557035777)

4 4 (object header) 5b 00 00 00 (01011011 00000000 00000000 00000000) (91)

8 4 (object header) 00 31 4f 1c (00000000 00110001 01001111 00011100) (474951936)

12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)

16 4 int UserEntity.a 0

20 4 (loss due to the next object alignment)

Instance size: 24 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

基本数据类型占多少字节

1、bit --位:位是计算机中存储数据的最小单位,指二进制数中的一个位数,其值为“0”或“1”。

2、byte --字节:字节是计算机存储容量的基本单位,一个字节由8位二进制数组成。在计算机内部,一个字节可以表示一个数据,也可以表示一个英文字母,两个字节可以表示一个汉字。

64位/8

1Byte=8bit (1B=8bit)

1KB=1024Byte(字节)=8*1024bit

1MB=1024KB

1GB=1024MB

1TB=1024GB

int 32bit 4

short 16bit 2

long 64bit 8

byte 8bit

char 16bit

float 32bit

double 64bit

boolean 1bit

  

以上是 JVM 中 java 对象布局 的全部内容, 来源链接: utcz.com/z/393265.html

回到顶部