参考文档:cloud.tencent.com/developer/a…
单位换算关系
首先我们得知道在计算机中所有数据都是由0 1
来组成的,那么存储0 1
这些二进制数据是由什么存放呢?就是由bit
存放的,一个bit
存放一位二进制数字。所以bit
是计算机最小的单位。
大部分计算机目前都是使用8位的块,就是我们上面称之为的字节Byte
,来作为计算机容量的基本单位。所以我们一般称一个字符或者一个数字都是称之为占用了多少字节。
了解了上面关于位和字节的关系后,我们可以看一下其他的单位换算关系
- 1B(Byte 字节) = 8bit(位)
- 1KB = 1024B
- 1MB = 1024KB
- 1GB = 1024MB
- 1TB = 1024GB
Java中对象占用多少内存
在HotSpot虚拟机中,对象在内存中存储的布局可以分为三个区域:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)。
对象内存 = 对象头内存「12|16」 + 实力数据大小「(num引用类型 * 4|8) + (num基本类型 * b)」 + 填充数据大小
对象头
在对象头中存储了两部分数据
- 运行时数据:存储了对象自身运行时的数据,例如哈希码、GC分代的年龄、锁状态标志、线程持有的锁、偏向线程ID等等。这部分数据在32位和64位的虚拟机中分别为32bit和64bit
- 类型指针:对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。如果对象是一个Java数组的话,那么对象头中还必须有一块用于记录数组长度的数据(占用4个字节)。所以这是一个指针,默认JVM对指针进行了压缩,用4个字节存储。 以虚拟机为64位的机器为例,那么对象头占用的内存是8(运行时数据)+4(类型指针)=12Byte。如果是数组的话那么就是16Byte
实例数据
实例数据中也拥有两部分数据,一部分是基本类型数据,一部分是引用指针。从父类中继承下来的变量也是需要进行计算。
基本类型数据
数据类型 | 占用内存(单位为Byte) |
---|---|
boolean | 1 |
byte | 1 |
short | 2 |
char | 2 「 Java中使用Unicode字符,所有的字符均以两个字节存储」 |
int | 4 |
float | 4 |
long | 8 |
double | 8 |
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的倍数,所以需要填充数据进行填充。
\