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

pcww981p  于 11个月前  发布在  Java
关注(0)|答案(2)|浏览(125)

当使用字面量创建字符串时,它存储在池中。但是当使用new操作符创建String对象时,它将对象存储在Heap中。
但是堆中的对象仅仅是一个指向存储在池中的文字的指针,还是一个存储在堆中的简单的String对象,适合GC?

68de4m5k

68de4m5k1#

术语:

  • 常量池是(每个).class文件中包含各种常量(包括字符串)的区域。常量池中不存在 runtime 对象。它是 file 的区域。
  • 字符串池是JVM用来管理特定类型字符串的运行时数据结构(具体地说,是对应于文字的String对象,以及由String::intern()添加到池中的String对象)。

你的问题实际上是在谈论字符串池,而不是常量池。
回答您的问题:
字符串池-字符串总是存在于常量池中吗?
不可以。使用new String()创建的字符串对象在字符串池或常量池中都不存在。
当使用literal创建string时,它会存储在pool中。
字符串(在加载的类文件的常量池中表示)被创建为String对象并添加到字符串池中(这些步骤发生在Java代码首次使用文字之前或使用文字时,具体细节取决于JVM实现)。
但是当new操作符用于创建String对象时,它将对象存储在Heap中。
是的。但是字符串池也是堆的一部分。就像我说的,它是一个数据结构,而不是一个存储区域。
(In过去,字符串池存在于一个特殊的堆中,叫做PermGen堆。但是PermGen被其他东西(MetaSpace)取代了,字符串池不再使用任何一个。
但是堆中的对象仅仅是一个指向存储在池中的文字的指针,还是一个存储在堆中的简单的String对象,适合GC?
这真的很混乱。
所有的字符串在(a)堆中都被表示为String对象。这包括字符串池中的字符串。即使字符串池在PermGen中。
所有无法访问的String对象都有资格进行垃圾收集。即使是字符串池中的字符串。即使是表示字符串字面量的String对象。
但是...等等...字符串文字可以被垃圾收集吗?
是的,我会的!如果一个表示字符串文字的String对象在运行时变得不可访问,它就有资格接受垃圾收集,就像任何其他String对象一样。
如果使用字符串文字的代码对象变得不可访问,则字符串文字可能变得不可访问。当类加载器变得不可访问时,可能会发生这种情况,并且发生类卸载。
是的,PermGen被垃圾回收了,至少从JDK 1.2开始是这样。(IIRC Java 1.0,也许1.1没有为PermGen堆实现GC。但这在很久以前就被修复了。)

qv7cva1a

qv7cva1a2#

它是一个存储在堆中的String对象,适合GC。我使用的是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次,创建String“a”需要2100- 4900 ns,创建String“b”需要4900- 15500 ns,所以创建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。

相关问题