这世界上没有优秀的理念,只有脚踏实地的结果 。
注释:文章中使用64位 JVM
一、对象种类:
1、正常对象
如: Object obj = new Object();
2、数组对象
如: String[] array = {"1", "2", "3"};
二、对象的组成部分:
1、对象头(Header)
(1):Mark Word:主要用来表示对象的线程锁状态,另外还可以用来配合GC、存放该对象的hashCode;占用空间大小:64bit 8byte。
2):Class Pointer 指针:是一个指向方法区中Class信息的指针;占用空间,开启指针压缩:32bit,4byte。未开启指针压缩:64bit,8tyte。
3):数组长度:存放数组对象的长度;占用空间:32bit,4byte。
2、实例数据(Instance Data)
存放类的所有成员变量,创建一个空对象的时候此处不占内存。
3、对齐填充(Padding)
对齐填充不是一定有的,如果对象头和实例数据加起来刚好是8byte的整数倍,那么就不需要对齐填充。
三、代码示例
首先我们先引入一个依赖,他可以帮我们分析JVM中对象布局等信息。
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.10</version>
</dependency>
1、执行普通对象
我们写一段测试代码如下:
public static void main(String[] args) {
//创建一个Object对象
Object o = new Object();
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
执行之前我们配置一个jvm参数:-XX:+UseCompressedOops 指针压缩,jdk1.8 jvm默认是开启指针压缩的。
1、开启指针压缩:-XX:+UseCompressedOops
执行结果如下:
占用内存:markword(8byte)+classpointer(4byte)+padding(4byte)=16byte。
2、关闭指针压缩:-XX:-UseCompressedOops
执行上述代码:
占用内存:markword(8byte)+classpointer(8byte)=16byte。
2、执行数组对象
同理我们也是分两种情况,开启和不开启指针压缩。
我们再写一段代码:
public static void main(String[] args) {
//创建一个空数组
String [] array = new String[]{};
System.out.println(ClassLayout.parseInstance(array).toPrintable());
}
1、开启指针压缩:
占用内存:markword(8byte)+classpointer(4byte)+数组长度(4byte)=16byte。
2、关闭指针压缩:
占用内存:markword(8byte)+classpointer(8byte)+数组长度(4byte)+padding(4byte)=24byte。