这是 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";
}
getUsage().toString()
我检查了永久代对象上使用的 perm gen 使用情况MemoryPoolMXBean
(在 u21 中称为“PS Perm Gen”,尽管它具有不同版本或不同垃圾收集器的名称略有不同。
当我第一次引用该类时,例如通过 read Big0.class
, perm gen 跳跃了 ~500 KB - 这是我所期望的,因为字符串的常量池编码是 UTF-8,并且我只使用 ASCII 字符。
然而,当我实际创建这个类的一个实例时,perm gen 会跳跃约 2 MB。由于这是一个 1 MB 的内存字符串(每个 UTF16 字符 2 个字节,当然没有代理),我对为什么内存使用量是两倍感到困惑。
如果我将字符串设为静态,也会出现同样的效果。如果我使用 final,它会编译失败,因为我超过了 65535 字节的常量池项目的限制(不知道为什么关闭 final 也可以避免这种情况——考虑一下这是一个额外的问题)。
任何见解表示赞赏!
编辑:我还应该指出,这发生在非静态、最终非静态和静态字符串中,但不适用于最终静态字符串。由于这已经是字符串常量的最佳实践,也许这主要是学术兴趣。