有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

空Java字符串的大小

我听到一位同事说,如果我在Java类中删除了一个字符串成员,即使该字符串是空的,我也会支付“24字节”。准确吗?整型、浮点型、双精度型都一样吗?(与int、float、double相反,它们分别只有4、4和8个字节)


共 (4) 个答案

  1. # 1 楼答案

    字符串由对象头(热点上2个单词,J9上3个单词)、int字段和char数组引用组成。Char数组本身由头、int字段和数组的其余部分组成。所有内容都填充到8字节。通常,字符编码为每个字符2个字节。一些JVM可以对char使用替代编码。J9一度可以用UTF8编码字符串。如果字符串由简单字符组成(基本上是UTF-8的1字节编码符号,如英语字母表、数字等),现代热点将使用每个字符1字节。否则,整个数组每个字符使用2个字节

    所以空字符串的深度大小是:

    • 32位热点上的32字节(16字节表示字符串,16字节表示字符[])
    • 64位热点上有56个字节(32个字节表示字符串,24个字节表示字符[])
    • 64位热点上有40个字节,带有压缩引用(24个字节表示字符串,16个字节表示字符[])

    通常,空字符数组不会被分配,因为它的值会被推断出来。毕竟,所有空字符数组都是相等的。因此,空字符串的实际惩罚将是一个浅字符串大小;对于当今最常见的情况(带有压缩ref的64位热点),它是24字节

    IBM J9 JVM有更大的对象头,它会分配一些more.

  2. # 2 楼答案

    您将为参考支付4或8个字节。是否为“容器”对象的每个实例支付额外的对象,取决于如何获得空字符串。例如,如果您使用文本"",那么所有实例都将引用同一个对象,因此您只需支付引用本身的费用

    如果要为每个实例创建一个单独的空字符串,那么显然这将占用更多内存

  3. # 3 楼答案

    借用自this answer:程序为空字符串打印32字节(为字符串池中的“”打印0字节)

    public static void main(String... args) {
        long free1 = free();
        String s = "";
        long free2 = free();
        String s2 = new String("");
        long free3 = free();
        if (free3 == free1) System.err.println("You need to use -XX:-UseTLAB");
        System.out.println("\"\" took " + (free1 - free2) + " bytes and new String(\"\") took " + (free2
                - free3) + " bytes.");
    }
    
    private static long free() {
        return Runtime.getRuntime().freeMemory();
    }
    
  4. # 4 楼答案

    的确,你会为一个整数付出比一个整数多得多的代价。我记得我检查过几个Java版本,整数花费了大约24字节。 只要字符串指向一个空对象(也称为nothing),你就只在内存中保留一个指针,我认为JVM不会保留一个位置来初始化它,在这种情况下,你不会浪费24个字节,只有8个字节。如果创建了字符串(即使是空字符串“”),那么内存中已经有了一个对象,而且由于所有对象都继承了对象,因此它们会带来一些负担,占用的内存比您直观预期的要多。 根据您对字符串的使用情况,一个常见的解决方案是从一个空对象开始,并在需要时延迟初始化它