字符串池 - 字符串总是存在于常量池中吗?

问题描述 投票:0回答:2

当使用文字创建字符串时,它会存储在池中。但是当使用new运算符创建String对象时,它会将对象存储在Heap中。

但是堆中的对象只是一个指向存储在池中的文字的指针,还是存储在堆中的一个简单的 String 对象,适合 GC?

java string new-operator pool
2个回答
9
投票

术语:

  • 常量池是(每个).class 文件中的一个区域,其中包含各种常量,包括字符串。常量池中不存在runtime对象。它是文件的一个区域。

  • 字符串池是 JVM 用于管理某些类型字符串的运行时数据结构。 (具体来说,

    String
    对应于文字的对象,以及由
    String
    添加到池中的
    String::intern()
    对象。)

你的问题实际上是在谈论字符串池,而不是常量池。


回答您的问题:

字符串池——字符串总是存在于常量池中吗?

不。使用

new String()
创建的字符串对象在字符串池和常量池中都不存在。

当使用文字创建字符串时,它会存储在池中。

字符串(已经!)存在于常量池中,并在字符串池中创建为 Java

String
对象。 (实际创建可以在类加载时,或者第一次使用文字时。这取决于 Java 实现。)

但是当使用new运算符创建String对象时,它会将对象存储在Heap中。

是的。但字符串池也是堆的一部分。就像我说的,它是一种数据结构,而不是存储区域。

(过去,字符串池位于一个称为 PermGen 堆的特殊堆中。但是 PermGen 被其他东西(MetaSpace)取代,并且字符串池不再使用任何一个......。

但是堆中的对象只是一个指向存储在池中的文字的指针,还是存储在堆中的一个简单的 String 对象,适合 GC?

这真的很混乱。

所有字符串都表示为 (a) 堆中的

String
对象。这包括字符串池中的字符串。即使字符串池位于 PermGen 中。

所有无法访问的

String
对象都有资格进行垃圾回收。即使对于字符串池中的字符串也是如此。即使对于表示字符串文字的
String
对象也是如此。

但是……等等……那么字符串文字可以被垃圾收集吗?

是的!!如果表示字符串文字的

String
对象在运行时变得无法访问,则它有资格进行垃圾回收,就像任何其他
String
对象一样。

如果使用字符串文字的代码对象变得无法访问,则该字符串文字可能会变得无法访问。当类加载器变得无法访问时,就会发生这种情况。

是的,永久代垃圾收集了。至少从 JDK 1.2 开始。 (IIRC Java 1.0 或许 1.1 没有为 PermGen 堆实现 GC。但这很早之前就被修复了。)


0
投票

它是一个存储在适合GC的堆中的String对象。我正在使用 Amazon Corretto 17。

我发现了令人困惑的解释,所以我决定用代码进行调查,通过运行测试来比较每种情况下的 String 对象创建时间:

startTime = System.nanoTime();
String a = "a";
endTime = System.nanoTime();
System.out.println(endTime - startTime);

startTime = System.nanoTime();
String b = new String("b");
endTime = System.nanoTime();
System.out.println(endTime - startTime);

在我的机器上运行上述10次,创建字符串“a”需要2100-4900ns,创建字符串“b”需要4900-15500ns,因此创建b必须做一些比创建a更昂贵的事情.

然后我使用 String.intern() 方法比较了具有相同字符集的 String 对象的引用,该方法返回对字符串池中 String 对象的引用。

String c = "hello";
String d = new String("hello");
System.out.println(c==d); // false
System.out.println(c==c.intern()); // true
System.out.println(d==d.intern()); // false
System.out.println((c.intern()==d.intern())); // true

通过这些,我们可以推断出c和d指向不同的对象,c是字符串池中的String对象(从Java8开始存储在非堆内存中),d是堆中的String对象。关于GC,我认为只有当字符串池所在的非堆内存达到限制时,字符串池才会被垃圾收集。该内存似乎被称为 Metaspace 并取代了 PermGen。

© www.soinside.com 2019 - 2024. All rights reserved.