抄录于 https://www.cnblogs.com/jssj/p/14348271.html
《Java 底层原理》Jvm对象结构和指针压缩
前言
Java 程序调优是一个程序员必备的技能。
对象内存结构
对象头:
Mark Word :32bit机 4B;64bit机 8B 是固定的。
类型指针:klass pointer,引用类型在方法区的地址。 开启指针压缩占4字节,不开启占8个字节。
数组长度:对象不是数组占0字节,对象是数组占4字节,开启指针压缩,数组长度会放到类型指针的后半段。
对其填充:在关闭指令压缩的情况下,数组类型还会进行填充,称为两段填充,还有很多中情况会出现填充。
实例数据:
类的非静态属性,基础数据类型(byte 1字节,int 4字节,等等),引用类型:开启指针压缩4B,不开8字节。
对齐填充:
保证Java对象的大小都是8字节的整数倍,不足就不起, 例如对象前面的信息计算下来是31个字节,那就会补一个字节成32个字节。对齐填充的出现原因和内存分配有关,不需要获取哦对象信息还要去多块内存获取组合。
计算对象大小
百度网盘: https://pan.baidu.com/s/1bk_qdV1jpo7qSBnLGJHgcw 提取码: jafj 下载一个Jar包。
import org.openjdk.jol.info.ClassLayout; public class JvmTest4 { public static void main(String[] args) { Student student = new Student(); System.out.println(ClassLayout.parseInstance(student).toPrintable()); } }
运行结果:
-XX:+/-UseCompressedOops -- 开启或者关闭指针压缩。
案例
import org.openjdk.jol.info.ClassLayout; public class JvmTest4 { static int[] a = new int[]{1,2,3}; public static void main(String[] args) { System.out.println(ClassLayout.parseInstance(a).toPrintable()); } }
运行结果:
这个案例是关不指针压缩下运行的, 可以很好的看到有两阶段提交的功能。
指针压缩
因为Java对象是8字节对齐的,所有对象对应的字节最后3位一定是000,故存储的时候可以去掉后面3个0。
面试题:Java堆内存最大允许多少,为什么?
对象头中的类型指针指向的就是对象引用变量在方法区的地址,通过这个地址可以找到整个对象的全部内容在内存中位置。
类型指针在开启指针压缩的情况下,占用4个字节即32位,2的32次方就是4G,类型指针最大可以存在4G内存的位置。 又因为每个对象在开启指针压缩的情况下,最后3位000会被去掉。 所以实际4个字节可以表示 2的35次方-2的3次方的最大内存地址,即32G内存的最大位置。
因为现在都是64位机器了,那么如果电脑或者服务器的内存超过32G内存,在开启指针压缩的情况下就是出现找不到内存地址情况?
如果在开启指针压缩下优化这个问题,可以将Java对象的8字节对齐改成16字节对其,甚至32字节对其。这个能表示的内存最大值就是64G,128G了。 这个需要修改JDK源码。
总结
Jvm的对象的结构,指针压缩对我们后续遇到问题,能够提供非常好的基础铺垫。