《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的对象的结构,指针压缩对我们后续遇到问题,能够提供非常好的基础铺垫。

posted @ 2021-02-09 16:42  加速丨世界  阅读(702)  评论(0编辑  收藏  举报