关于java:一道阿里面试难题如何计算JAVA对象大小

46次阅读

共计 1764 个字符,预计需要花费 5 分钟才能阅读完成。

在做 JVM 内存调优的时候,咱们免不了须要去计算对象的大小。计算对象大小又要思考是一般对象还是数组对象,因为一般对象与数组对象的对象头存在些许差别。而且自 JDK6 当前,为了节俭内存、进步运行效率,又引入了新的技术:指针压缩。更加剧了计算对象大小的难度。

这篇文章就来深入分析如何计算对象大小,确保计算的后果与理论状况不差一个字节。

对象构造

对象构造想必深刻学习过 JVM 的人都晓得,它分为三大部分:对象头、实例数据、对齐填充。其中对象头又分为三个局部:Mark Word、类型指针、数组长度。其实对象头还有第四局部,这是目前你看到的书、视频都没有提到的,对象头也有对齐填充局部,这个局部也不是肯定会有,只有数组对象在未开启指针压缩的状况下才会呈现。是不是一脸懵,那就持续往后看。

指针压缩

看到这四个字是不是一堆的问号:这是什么?这怎么实现的?为什么说它节俭了内存?……咱们就来搞清楚这些个问题。

咱们先达成观点上的统一:所有的对象都是以 8 字节对齐的。当初我有 3 个对象:test1(16 字节)、test2(32 字节)、test3(24 字节),为了便于阐明,如果这三个对象两头没有其余对象,那他们的内存地址是:

test1 = 0x0000 0 000(0 字节 ~ 16 字节)test2 = 0x0001 0 000(16 字节 ~ 48 字节)test3 = 0x0011 0 000(48 字节 ~ 72 字节)

大家发现法则了吗,所有对象指针的后三位都是 0,这就是指针压缩的实现原理。开启指针压缩后,JVM 会将对象指针的后三位给截去,如果 test2 = 0x10000,在开启指针后就变成了 test2=0x10,在应用的时候将后三位的 0 补回去,即 test2=0x10 000。

因为开启了指针压缩后,对象指针就变成了 4 字节(32 位),加上补 3 位,共 35 位。即开启指针压缩后一个对象指针能示意的最大堆空间是 2 的 35 次方,即 32G。

那读者能够想一想?如果我想裁减一个 oop 能示意的堆空间大小该怎么做呢?

上面咱们来看四种状况(一般对象 - 敞开指针压缩、一般对象 - 开启指针压缩、数组对象 - 敞开指针压缩、数组对象 - 开启指针压缩)下的对象大小是如何计算出来的。倡议读者写类似代码测试一下,这样能力了解得更粗浅。

测试代码:

package com.qimingnan.adjust;

import org.openjdk.jol.info.ClassLayout;

public class Test1 {
    int a = 10;
    int b = 20;

    static int[] arr = {0, 1, 2};

    public static void main(String[] args) {Test1 test1 = new Test1();

        System.out.printf(ClassLayout.parseInstance(test1).toPrintable());
        System.out.printf(ClassLayout.parseInstance(arr).toPrintable());
    }
}

一般对象

一、未开启指针压缩

24B = 8B(Mark Word)+ 8B(KClass Pointer)+ 4B + 4B

二、开启指针压缩

24B = 8B(Mark Word)+ 4B(KClass Pointer)+ 4B(int a)+ 4B(int b)+ 4B(Padding)

数组对象

一、未开启指针压缩

40B = 8B(Mark Word)+ 8B(KClass Pointer)+ 4B(数组长度)+ 4B(头部 Padding)+ 12B(3 个 int)+ 4B(对象 Padding)

二、开启指针压缩

32B = 8B(Mark Word)+ 4B(KClass Pointer)+ 4B(数组长度)+ 12B(3 个 int)+ 4B(对象 Padding)

如何计算对象大小大家学会了吗?

介绍一款工具,jol,大家在做测试的时候能够借助这个工具

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.10</version>
</dependency>

这篇文章有些中央可能不太好了解,读者有问题的话,留言发问吧。我都会一一回复。

后续我将为大家新开《手写 JVM》的系列专栏,如果你对此感兴趣的话,那么就关注我吧。

正文完
 0