阿里面试题:一个 String 字符串占多少内存?

最近一个网友问我,在面试阿里的时候,被问到了一个 String 字符串占用多少内存的问题?他当时懵了,因为他只记得基本数据类型占用的空间大小。

说实话,这个问题,如果是我,我也可以会回答错误。

网上曾经有一道非常著名的题,如下:

既然选项是字节,那我们就应该这么算。

String str = "搞java";  
System.out.println("\"搞java\".length():" + (str.length()));  
System.out.println("\"搞java\".getBytes().length:" + (str.getBytes().length));  
System.out.println("\"搞java\".getBytes(\"GBK\").length:" + (str.getBytes("GBK").length));  
System.out.println("\"搞java\".getBytes(\"UTF-8\").length:" + (str.getBytes("UTF-8").length));  
/**
"搞java".length():5
"搞java".getBytes().length:6
"搞java".getBytes("GBK").length:6
"搞java".getBytes("UTF-8").length:7
*/

所以,选 A 或选 B 都说得过去。但是这是一个单选题,官方给出的最终正确答案是 A,即 6 个字节。原因是,我们的 Window 系统,默认的是 GBK,所以,答案为 A。

现在我们回归到的主题,一个 String 字符串占多少内存?就如上面这个选择题一样,看起来比 long 和 double 都要节约空间?

搜寻了好久,国外网友给出了一个计算公式:

这个公式看的我糊里糊涂的,我们看看 String 的源码。里面有一个 int 的 hash,还有一个 char [] 数组。所以,单纯的讲上面的字符串占用的空间肯定不止 6 个字节。

根据上面这个图,我们可以看出 String 对象的一个基本内存布局情况。需要注意的是 JDK 6 和 JDK 8 String 对象有所改动,计算方式不一样。

由上图可知,一个空 String 所占空间为:

对象头(8 字节)+ char 数组(16 字节)+ 3 个 int(3 × 4 = 12 字节)+1 个 char 数组的引用 (4 字节 ) = 40 字节。这里是 JDK 6 的计算方法。

JDK 8 中,只有一个 int 了,所以一个空的 String 占用 32 字节。

所以,我们最终可以总结一个公式

// JDK 6
8*( ( 8+2*n+4+12)+7 ) / 8 = 8*(int) ( ( ( (n) *2 )+43) /8 )
// JDK 8
8*( ( 8+2*n+4+4)+7 ) / 8 = 8*(int) ( ( ( (n) *2 )+43) /8 )

其中 N 为字符串长度。

那个这个题,该怎么回答呢?说出你的思路,你对 String 内部结构的构成理解,和计算方式就可以了。实在记不住,也可以使用 Java 自带的 jol-core 工具来计算。

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

引入上面的 pom 配置,然后编写简单的几行代码就可以计算出来。

public class XttblogObjectMemory {
    public static void main(String[] args) {
        System.out.print(ClassLayout.parseClass(String.class)
            .toPrintable());
    }
}

空字符串的内存占用情况,计算结果如下所示:

java.lang.String object internals:
     OFFSET  SIZE     TYPE DESCRIPTION                   VALUE     
     0      12          (object header)                  N/A     
     12     4   char[] String.value                      N/A     
     16     4      int String.hash                       N/A
     20     4          (loss due to the next object alignment)
Instance size: 24 bytes

其他 Java 类的内存占用情况,也可以通过 jol-core 工具统计出来,用法和上面的类似。

以上,你知道的越多,不知道的就越多,业余的像一棵小草一样。

发布了337 篇原创文章 · 获赞 2174 · 访问量 159万+

猜你喜欢

转载自blog.csdn.net/xmt1139057136/article/details/103760205