一个Java对象到底占用多大内存
Java对象的内存布局:对象头(Header),实例数据(Instance Data)和对齐填充(Padding)
对象占用的内存大小还受到VM参数是否开启指针压缩UseCompressedOops的影响
内存大小:(对象头 + 实例数据 + 对齐补充padding) % 8等于0 且 0 <= padding < 8
我所在的环境是64位HotSpot虚拟机,操作系统 64位Windows 7.以下例子均已不开启指针压缩,开启指针压缩计算方法类似,不再赘述
具体数据类型所占内存
一 对象头
对象头在32位系统上占用8bytes,64位系统上占用16bytes。
开启(-XX:+UseCompressedOops)对象头大小为12bytes(64位机器)。
MemoryCalculation.class类文件
import net.sourceforge.sizeof.SizeOf;
public class MemoryCalculation {
public static void main(String[] args) {
System.out.println(SizeOf.humanReadable(SizeOf.deepSizeOf(new MemoryCalculation ())))
}
}
编译执行:
javac MemoryCalculation.java -cp SizeOf.jar MemoryCalculation.java
java -javaagent:sizeOf.jar -XX:-UseCompressedOops MemoryCalculation
输出结果16.0b(对象头16 + 实例数据0 + 对齐补充0)
二 实例数据
原生类型(primitive type)的内存占用如下:
Primitive Type | Memory Required(bytes) |
---|---|
boolean | 1 |
byte | 1 |
short | 2 |
char | 2 |
int | 4 |
float | 4 |
long | 8 |
double | 8 |
reference类型在32位系统上每个占用4bytes, 在64位系统上每个占用8bytes。
三 数组对象
数组对象的对象头占用24个字节,启用压缩之后占用16个字节。
import net.sourceforge.sizeof.SizeOf;
public class MemoryCalculation {
public static void main(String[] args) {
System.out.println(SizeOf.humanReadable(SizeOf.deepSizeOf(new Integer[0])))
}
}
输出结果24.0b(对象头24 + 实例数据长度 * 数据长度 + 对齐补充0)
复合对象
import net.sourceforge.sizeof.SizeOf;
public class MemoryCalculation {
static class B {
int a;
int b;
}
static class C {
int ba;
B[] as = new B[3];
C() {
for (int i = 0; i < as.length; i++) {
as[i] = new B();
}
}
}
public static void main(String[] args) {
System.out.println(SizeOf.humanReadable(SizeOf.deepSizeOf(new C())));
}
}
内存图:
未开启压缩:
(16 + 4 + 8 + 4(padding)) + (24+ 8*3) +(16 + 8) * 3 = 152bytes
开启压缩:
(12 + 4 + 4 + 4(padding)) + (16 + 4*3 +4(数组对象padding)) + (12+8+4(B对象padding))*3= 128bytes
再看一个有意思的例子
import net.sourceforge.sizeof.SizeOf;
public class MemoryCalculation {
static class B {
int a;
int b;
}
static class C {
int ba;
B[] as = new B[3];
}
public static void main(String[] args) {
System.out.println(SizeOf.humanReadable(SizeOf.deepSizeOf(new C()))) ;
}
}
未开启压缩:
(16 + 4 + 8 + 4(padding)) + (24+ 8*3) + 0 = 80 bytes
问:为什么这里B对象所占内存为0呢?
答:因为创建对象时,只分配数组as的引用的内存,所指向的对象内存还未指定,即数据未初始化,此时所占内存为0,而前面的例子数组中所指的对象在构造函数中已初始化.
心得:
- 对这个学习主要是让自己对java内存中对象的布局和所占大小有个了解
- 发现对象中方法是不占用内存的
参考链接:
- https://blog.csdn.net/ykdsg/article/details/12080071.
- https://www.cnblogs.com/magialmoon/p/3757767.html.
资源下载: