gpt4 book ai didi

java - String interning 是否会导致 String 同时在堆内存和 native 内存中?

转载 作者:行者123 更新时间:2023-11-30 08:50:03 25 4
gpt4 key购买 nike

这是 String#intern 的 javadoc:

/**
* Returns a canonical representation for the string object.
* <p>
* A pool of strings, initially empty, is maintained privately by the
* class {@code String}.
* <p>
* When the intern method is invoked, if the pool already contains a
* string equal to this {@code String} object as determined by
* the {@link #equals(Object)} method, then the string from the pool is
* returned. Otherwise, this {@code String} object is added to the
* pool and a reference to this {@code String} object is returned.
* <p>
* It follows that for any two strings {@code s} and {@code t},
* {@code s.intern() == t.intern()} is {@code true}
* if and only if {@code s.equals(t)} is {@code true}.
* <p>
* All literal strings and string-valued constant expressions are
* interned. String literals are defined in section 3.10.5 of the
* <cite>The Java&trade; Language Specification</cite>.
*
* @return a string that has the same contents as this string, but is
* guaranteed to be from a pool of unique strings.
*/

假设我有下一个代码:

String ref1 = "ref";
String ref2 = ref1.intern();

在 ref 初始化的时候,ref1 是否还在堆中。我问是因为如果它在不删除原始引用的情况下实习字符串将使 java 进程使用的 RSS 内存加倍。

最佳答案

如果我们考虑你的例子,是的,ref1 仍然在堆中,但是因为 ref1ref2 都指向 相同实例。您使用字符串文字初始化 ref1,并且字符串文字会自动保留 as described here :

Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method 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

从常量池加载的字符串会自动驻留在字符串池中,结果为真,两个实例都引用同一个驻留对象。

2. true

str3 指的是一个已经被驻留的字符串实例。

3. false

str4 是一个新实例,与之前的实例无关。

4. false

一次性 str4 实例不指向自字符串池开始以来就存在的同一个对象。

5. true

str5 按预期指向我们的驻留字符串。

重要的是要注意,在 Java 7(Oracle 实现)之前,驻留字符串存储在 PermGem 中(因为 Java 8 不再存在),但自该版本以来,它们已被移动到堆中。因此,在大量使用实习功能时,使用较旧版本的 JVM 可能会出现特殊的内存问题。

有关如何在不同版本中管理 interned 字符串的更多信息,请查看这个不错的 post .

关于java - String interning 是否会导致 String 同时在堆内存和 native 内存中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31175205/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com