10

当我们说实习字符串存储在永久代区域中时,字符串文字也同样适用吗?还是仅适用于由 inter() 执行的字符串?

实际上博客文章通常说字符串池包含对字符串对象的引用,而实际的字符串对象在堆中的某个地方。永久代是在堆内还是在堆外也有很多困惑。(我使用了 jcosole,它显示的永久 gen 与堆不同。许多帖子说它是堆的一部分,许多人说它是不同的)

编辑: 当我跑的时候:

public class stringtest2{
  public static void main(String args[]){
    int i=0;
    List<String> list=new ArrayList<String>();
    while(true){
      String s="hello"+i;
      String s1=i+"hello";
      String s2=i+"hello"+i;
      System.out.println(s);
      s.intern();

      s1.intern();
      s2.intern();
      list.add(s);
      list.add(s1);
      list.add(s2);
      i++;
    }
  }
}

我期待Java.lang.OutOfMemoryError: PermGen space但我得到了:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOf(Arrays.java:2760)
        at java.util.Arrays.copyOf(Arrays.java:2734)
        at java.util.ArrayList.ensureCapacity(ArrayList.java:167)
        at java.util.ArrayList.add(ArrayList.java:351)
        at stringtest2.main(stringtest2.java:20)

难道不应该Java.lang.OutOfMemoryError: PermGen space

4

3 回答 3

6

当我们说实习字符串存储在永久代区域中时,字符串文字也同样适用吗?

文字字符串被保留。所以是的,在 Java 6-.

从 Java 7 开始,interned 字符串不再存储在永久代中。它们像您要创建的任何其他对象一样存储在堆的主要部分。

不应该是 Java.lang.OutOfMemoryError: PermGen space

您得到的异常是由创建一个位于堆上的数组引起的。要尝试获得“永久内存不足”错误,您可以尝试删除这些list.add()行。但是请注意,可以对实习字符串进行垃圾收集,因此即使这样做也不会导致您期望的异常。

参见 RFE 6962931 :

在 JDK 7 中,interned 字符串不再分配在 Java 堆的永久代中,而是与应用程序创建的其他对象一起分配在 Java 堆的主要部分(称为年轻代和年老代)中. 此更改将导致更多数据驻留在主 Java 堆中,而永久代中的数据更少,因此可能需要调整堆大小。由于此更改,大多数应用程序只会看到相对较小的堆使用差异,但加载许多类或大量使用 String.intern() 方法的大型应用程序将看到更显着的差异。

于 2012-11-14T11:35:59.137 回答
2

StringJavaDoc中所述,所有 String 字面量都是自动实习的:

所有文字字符串和字符串值的常量表达式都是实习的。

我希望您手动实习的字符串和任何字符串文字之间的行为是一致的。

于 2012-11-14T11:28:11.310 回答
0

s.intern()返回对实习字符串的引用,但您没有使用它。尝试s = s.intern()

于 2013-03-21T21:54:23.727 回答