本地字符串文字的内存分配?

4
我知道当我们创建字符串文字时,它会放在永久代空间中。我的问题是,即使该字符串文字只在方法中使用,它是否会一直存在于jvm的生命周期中。例如,我有以下代码片段:
private static void testString1(){
        String str1="tetingLiteral";
    }


private static void testString2(){
        String str2="tetingLiteral";
    }

现在我从主方法中调用了以下内容:
testString1();
testString12();

str1和str2会引用同一块内存位置。

我的理解是,它们将引用同一块内存位置(即使在方法内创建字符串常量,它也会在jvm生命周期内保留在那里)。但是我仍然想确认一下,因为我无法通过编程方式检查它,因为没有办法打印字符串内存位置。


1
获取有关字符串内存位置的信息有两种方法。(1) 如果两个字符串引用都为null或都引用同一个字符串对象,则==比较为true。(2)System.identityHashCode尽可能为每个不同的对象返回不同的值。 - Patricia Shanahan
2个回答

9

以下是从Java语言规范第3.10.5节中的内容翻译:

此外,字符串字面值始终指向String类的同一实例。这是因为字符串字面值 - 或者更一般地说,作为常量表达式的值(§15.28)的字符串 - 被“interned”以共享唯一实例,使用方法String.intern。

(请参见下面的示例,它显示字符串插入也适用于不同包中的类。)


5

具体实现方式取决于JVM,但在Oracle Java 7中,字符串文字存储在堆上,并且可以在没有任何类使用该字符串文字(因为它们已被卸载)时清除。


这是否意味着它们将在正常的GC运行时一起被清理? - emilly
我怀疑它们只会在进行完整的垃圾回收时才被清理。在Java 8中,永久代将被移除,类也将存在于堆上。 - Peter Lawrey
Peter,还有一件事情,了解Java 7将字符串字面量存储在堆上的原因会很有帮助(是因为字符串字面量是导致PermGen错误的最大贡献者之一吗?)。另外,为什么在Java 8中,PermGen将被移除,类也将存储在堆上? - emilly
抱歉问得太多了。但是你提供了全新的信息,我忍不住要问这个问题。 - emilly
1
据我所知,许多人认为调整两个空间太复杂了。使用单个堆简化了设计和调整。在JEE系统中,permgen很容易填满。我认为使用最少的简单库是一件好事,它有一个好处,就是永远不会填满您的perm gen。 - Peter Lawrey

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