计算对象占的内存大小

157 阅读4分钟

参考文档:cloud.tencent.com/developer/a…

单位换算关系

首先我们得知道在计算机中所有数据都是由0 1来组成的,那么存储0 1这些二进制数据是由什么存放呢?就是由bit存放的,一个bit存放一位二进制数字。所以bit是计算机最小的单位。

大部分计算机目前都是使用8位的块,就是我们上面称之为的字节Byte,来作为计算机容量的基本单位。所以我们一般称一个字符或者一个数字都是称之为占用了多少字节。

了解了上面关于位和字节的关系后,我们可以看一下其他的单位换算关系

  1. 1B(Byte 字节) = 8bit(位)
  2. 1KB = 1024B
  3. 1MB = 1024KB
  4. 1GB = 1024MB
  5. 1TB = 1024GB

Java中对象占用多少内存

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

对象内存 = 对象头内存「12|16」 + 实力数据大小「(num引用类型 * 4|8) + (num基本类型 * b)」 + 填充数据大小

对象头

在对象头中存储了两部分数据

  • 运行时数据:存储了对象自身运行时的数据,例如哈希码、GC分代的年龄、锁状态标志、线程持有的锁、偏向线程ID等等。这部分数据在32位和64位的虚拟机中分别为32bit和64bit
  • 类型指针:对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。如果对象是一个Java数组的话,那么对象头中还必须有一块用于记录数组长度的数据(占用4个字节)。所以这是一个指针,默认JVM对指针进行了压缩,用4个字节存储。 以虚拟机为64位的机器为例,那么对象头占用的内存是8(运行时数据)+4(类型指针)=12Byte。如果是数组的话那么就是16Byte

实例数据

实例数据中也拥有两部分数据,一部分是基本类型数据,一部分是引用指针。从父类中继承下来的变量也是需要进行计算。

基本类型数据

数据类型占用内存(单位为Byte)
boolean1
byte1
short2
char2 「 Java中使用Unicode字符,所有的字符均以两个字节存储」
int4
float4
long8
double8

Java引用类型
在一个对象中除了有基本数据类型以外,我们也会有一些引用类型. 引用类型的对象比较特殊,因为这些对象真正存储在虚拟机中的堆内存中,对象中只是存储了一个引用而已,如果是引用类型那么就会存储一个指向该引用的指针。指针默认情况下是占用4字节,是因为开启了指针压缩,如果没有开的话,那么一个引用就占用8个字节。

实例数据 = (num引用类型 * 4|8) + (num基本类型 * b)

对齐填充

对齐填充并不是必然存在的,也没有特别的含义。它仅仅起着占位符的作用。由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说就是对象的大小必须是8字节的整数倍。而如果对象头加上实例数据不是8的整数倍的话那么就会通过对其填充进行补全。

String占用多少内存

private final char value[]; private int hash; // Default to 0
在String类中有两个属性,其中对象头固定了是12字节,int是4字节,char[]数组其实在这里相当于引用对象存的,所以存的是地址,因此占用4个字节,所以大小为对象头12Byte+实例数据8Byte+填充数据4Byte=24Byte 这里的对象头和实例数据加起来不是8的倍数,所以需要填充数据进行填充。

\