字符串文字使用2倍的预期永久生成空间量

Bee*_*ope 5 java memory string jvm permgen

这是Sun JDK 1.6u21,x64.

我有一个类用于试验perm gen用法,它只包含一个大字符串(512k字符):

public class Big0 {
     public String bigString =
         "A string with 2^19 characters, should be 1 MB in size";
}
Run Code Online (Sandbox Code Playgroud)

我检查使用烫发根的使用getUsage().toString()MemoryPoolMXBean为永久生成(在21岁以下称为"PS烫发根"对象,尽管它有不同的版本,或者与不同的垃圾收集器略有不同的名称.

当我第一次引用类时,通过读取来说Big0.class,perm gen跳过~500 KB - 这就是我所期望的,因为字符串的常量池编码是UTF-8,而我只使用ASCII字符.

然而,当我实际创建这个类的实例时,perm gen会跳跃大约2 MB.由于这是1 MB内存中的字符串(每个UTF16字符2个字节,当然没有代理),我很困惑为什么内存使用量是双倍的.

如果我将字符串设为静态,则会产生相同的效果.如果我用最后的,它不能作为编译我超过65535个字节常量池项的上限(不知道为什么最后留下关闭避免了要么 - 认为这是一个加分题).

有任何见解赞赏!

编辑:我还应该指出,这发生在非静态,最终的非静态和静态字符串中,但不适用于最终的静态字符串.由于这已经是字符串常量的最佳实践,也许这主要是学术兴趣.

Ron*_*Ron 2

我认为这是你的测试类的产物。我创建了一个类似的类,然后用javap反编译它。

[eclipse] java 编译器将 String 文字分成块,每个块不超过 64k。用于初始化非常量字段的字节码由将源字符串与一系列 StringBuilder 操作拼凑在一起组成。尽管最终的巨大字符串被保留,但它所组成的大原子占据了常量池中的空间。