程序员的公众号:源1024,获取更多资料,无加密无套路!
最近整理了一波电子书籍资料,包含《Effective Java中文版 第2版》《深入JAVA虚拟机》,《重构改善既有代码设计》,《MySQL高性能-第3版》,《Java并发编程实战》等等
获取方式: 关注公众号并回复 电子书 领取,更多内容持续奉上
关于new Object()的灵魂追问,一个Java对象占用多大内存?被面试官这么一问是不是有点蒙?
我们都知道Java是面向对象开发,几乎每天都在new对象,但却不知道对象的体重,实属有点尴尬,今天我们重新来认识下这个陪伴我们职业生涯的对象!
Java对象由对象头、类型指针、实例数据、填充数据组成,虚拟机要求对象大小必须是8字节的整数倍,为了保证对象中的成员变量都能够自然对齐。
mark word
占固定8个字节,主要用于标记对象的锁信息、hashcode、GC标记(三色标记)。
class pointer
类型指针占位4个字节或者8个字节(看是否开启类型指针压缩),开启类型指针压缩占位4个字节,反之占位8个字节。JDK1.8默认是开启类型指针压缩的。
通过以下命令查看java命令默认的启动参数
java -XX:+PrintCommandLineFlags -version
-XX:+UseCompressedClassPointers //开启压缩类指针
-XX:-UseCompressedClassPointers //关闭压缩类指针
-XX:+UseCompressedOops //开启压缩普通对象指针
-XX:-UseCompressedOops //关闭压缩普通对象指针
instance data
实例数据是存储对象真正的有效信息,如果是基本类型,直接存储下来,如果是引用类型,存储的是指向堆中对象的引用指针。非静态属性,生成对象时就是实例数据。
java分为两种数据类型:基本类型和引用类型
8种基本类型
类型 | 占用空间(byte) |
---|---|
boolean | 1 |
byte | 1 |
short | 2 |
char | 2 |
int | 4 |
float | 4 |
long | 8 |
double | 8 |
引用类型
对应的就是oops(Ordinary Object Pointers, OOPs)—— 普通对象指针,JVM开启普通对象指针压缩时为4个字节,反之为8个字节。
内容 | 32位 | 64位 |
mark word | 4byte | 8byte |
类型指针 | 4byte | 未开启压缩为8bit,开启压缩为4byte |
实例数据 | 0 | 0 |
填充数据(将最后的大小填充为8的倍数) | 0~7byte | 0~7byte |
总计 | 8byte | 开启压缩后,则8+4=12,对齐填充为8的倍数,最后为 16byte |
下面我们通过代码进行验证,使用 JOL 工具分析 Java 对象
maven依赖
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.2</version>
</dependency>
新建Demo类
public class Demo {
public static void main(String[] args){
ClassLayout classLayout = ClassLayout.parseInstance(new Demo());
System.out.println(classLayout.toPrintable());
}
}
输出结果
com.lly835.bestpay.model.Demo 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 f8 (00000101 11000001 00000000 11111000) (-134168315)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
我们看到Demo对象占16字节,对象头12字节+填充(4字节)
新建Demo2类
定义4个类型属性:boolean、int、double、Integer
public class Demo2 {
private boolean flag = true;
private int a = Integer.MAX_VALUE;
private double b = 0.01;
private Integer c = 5;
public static void main(String[] args){
ClassLayout classLayout = ClassLayout.parseInstance(new Demo2());
System.out.println(classLayout.toPrintable());
}
}
输出结果
com.lly835.bestpay.model.Demo2 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 f8 (00000101 11000001 00000000 11111000) (-134168315)
12 4 int Demo2.a 2147483647
16 8 double Demo2.b 0.01
24 1 boolean Demo2.flag true
25 3 (alignment/padding gap)
28 4 java.lang.Integer Demo2.c 5
Instance size: 32 bytes
Space losses: 3 bytes internal + 0 bytes external = 3 bytes total
我们看到Demo2对象占32字节,对象头12字节+int(4字节)+double(8字节)+boolean(1字节)+填充(3字节)+ Integer(4字节)
一个Java对象占用多大内存空间,你学会了吗?
系列文章索引
MyBatis的插件能在哪些地方进行拦截?
了解MyBatis的缓存机制吗
面试官:谈谈对volatile的理解
Spring中用到了哪些设计模式
面试官:说一下SQL的执行过程
线程池的工作原理