这是String #intern的javadoc:
String ref1 = "ref";
String ref2 = ref1.intern();
假设我有下一个代码:
{{1}}
在初始化ref的时候,ref1是否仍然在堆中。我问,因为如果它是没有删除原始引用的实习字符串将加倍java进程使用的RSS内存。
答案 0 :(得分:2)
如果我们考虑您的示例,是的,ref1
仍在堆中,但因为ref1
和ref2
都指向相同的实例。您使用字符串文字初始化ref1
,字符串文字自动实习as described here:
此外,字符串文字始终引用类String的相同实例。这是因为字符串文字 - 或者更常见的是作为常量表达式(§15.28)的值的字符串 - 被“实例化”以便使用String.intern方法共享唯一实例。
因此,没有双内存使用(如果你不认为字符串存在于保存类ConstantPool的内容和所有类结构信息的单独内存区域中。)
要详细解释实习如何实际工作,请参阅此示例:
public class Intern{
public static void main(String... args){
String str1="TestStr";
String str2="TestStr";
System.out.println("1. "+(str1==str2));
String str3=str1.intern();
System.out.println("2. "+(str1==str3));
String str4=new String("TestStr");
System.out.println("3. "+(str1==str4));
String str5=str4.intern();
System.out.println("4. "+(str4==str5));
System.out.println("5. "+(str1==str5));
}
}
你会得到这个输出:
1. true
从常量池加载的字符串会自动插入到字符串池中,结果为true,两个实例都引用相同的实体对象。
2. true
str3
指的是已经实习的字符串实例。
3. false
str4
是一个新实例,与之前的实例无关。
4. false
一次性str4
实例不指向自字符串池开头以来存在的同一对象。
5. true
str5
按预期指向我们的实习字符串。
值得注意的是,在Java 7(Oracle实现)之前,实习字符串存储在PermGem中(因为Java 8不再存在),但是从那个版本开始,它们已经被移动到堆中。因此,在大量使用实习功能时,可能会出现使用较旧版本的JVM特有内存问题。
有关如何在不同版本中管理实习字符串的其他信息,请查看此版本post。