字符串字面值和永久代内存区域

10

当我们说内部字符串(interned strings)存储在永久代区域时,这是否也适用于字符串字面量?还是只适用于通过intern()方法进行内部化的字符串?

实际上,博客文章通常会说字符串池包含对字符串对象的引用,而实际的字符串对象则存储在堆中的某个位置。此外,人们非常困惑永久代是在堆内还是在堆外(我使用了jconsole,它显示永久代与堆不同。许多文章将其视为堆的一部分,而其他文章则认为它是不同的)。

编辑: 另外,当我运行以下代码时:

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

3个回答

6
当我们说内部化字符串存储在永久代区域时,字符串字面量也是如此吗?
字面量字符串是被内部化的。所以,在Java 6中也是这样的。
从Java 7开始,内部化字符串不再存储在永久代中。它们像你创建的其他任何对象一样存储在堆的主要部分中。
它不应该是Java.lang.OutOfMemoryError: PermGen space吗?
你得到的异常是由生存在堆上的数组创建引起的。为了尝试获得“永久代内存不足”的错误,可以尝试删除list.add()行。但请注意,内部化字符串可以被垃圾回收,因此即使这样做仍无法引发您期望的异常。
参见RFE 6962931
在JDK 7中,字符串常量池不再分配在Java堆的永久代中,而是与应用程序创建的其他对象一起分配在Java堆的主要部分(即年轻代和老年代)中。这个改变将导致更多的数据驻留在Java堆的主要部分,较少的数据驻留在永久代中,因此可能需要调整堆大小。大多数应用程序由于这个变化只会看到相对较小的堆使用差异,但加载许多类或频繁使用String.intern()方法的大型应用程序将会看到更显著的差异。

Java.lang.OutOfMemoryError: Java heap space--但我正在使用Java 6更新29。所以我应该得到Java.lang.OutOfMemoryError: PermGen space - a Learner
1
@aLearner 异常是由 java.util.Arrays.copyOf(Arrays.java:2760) 抛出的,当 ArrayList 需要扩展其容量时调用该方法 - 因此堆空间错误是正常的。 - assylias

2
所有字符串字面量都会自动进行内部化,这在 String JavaDoc 中有所描述:

所有字面量字符串和字符串常量表达式都会被内部化。

我期望手动内部化的字符串与任何字符串字面量之间的行为是一致的。

是的,我也这么认为。否则行为将是不一致的,他们会在某个地方记录下来的。 - a Learner

0

s.intern() 返回一个指向已经被池化的字符串的引用,但是你没有使用它。 尝试使用 s = s.intern()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接