阅读完这些讨论后 - question 1,question 2,article
我对 Java String Constant Pool 有以下理解(请纠正我,如果我错了):
编译源代码时,编译器会在程序中查找所有字符串文字(放入双引号的字符串文字),并在堆区域中创建不同的(无重复)对象,并将其引用保存在名为的特殊内存区域中String 常量池(方法区域内的区域)。在运行时创建任何其他字符串对象。
假设我们的代码包含以下语句:
String a = "abc"; //Line 1
String b = "xyz"; //Line 2
String c = "abc"; //Line 3
String d = new String("abc"): //Line 4
编译上面的代码时,
第1行:一个String对象" abc"在堆中创建,此对象由变量 a 和字符串常量池引用。
第2行:编译器在字符串常量池中搜索对象" xyz"的任何现有引用。但是找不到一个。所以,它创造了对象" xyz"并将其引用放在String Constant Pool中。
第3行:这次编译器在字符串常量池中找到对象,并且不在池或堆中创建任何其他条目。变量 c 仅指现有对象,也由 a 引用。
第4行:第4行中的文字出现在字符串常量池中。因此,不再在游泳池中进入。然而,在运行时,为" abc"创建了另一个String对象。其参考文献存储在变量 d 。
中现在我有以下问题/怀疑:
答案 0 :(得分:1)
- 上面描述的具体是什么?
醇>
是的,但从概念上讲,常量池和字符串池是不同的东西。
constant pool是.class
文件的一部分,其中包含此类中使用的所有常量。
string pool是一个运行时概念 - 实习字符串和字符串文字are stored here。
这是常量池上的JVM specification。它是.class
格式部分的一部分。
- 编译器如何创建对象?据我所知,对象是在运行时创建的,而堆是运行时内存区域。那么,在编译时如何以及在何处创建String对象!
醇>
如何/当完全这种情况发生时,我相信,这是一个特定于JVM实现的细节(如果我错了,请纠正我),但基本的解释是每当JVM决定加载一个类时,常量池中找到的任何字符串都会自动放入运行时 字符串池中,并且可以使用任何重复项来引用同一个实例。
在其中一个相关答案的评论中,Paŭlo Ebermann says:
当在VM中加载类时,字符串常量将被复制到堆,到VM范围的字符串池
所以看起来这至少是Sun的VM如何实现字符串池。
在JDK 7 / HotSpot之前,实习字符串存储在permanent generation space中 - 现在它们存储在主堆中。
- 源代码可以在一台机器上编译,并在另一台机器上运行。或者,即使在同一台机器上,它们也可以在不同的时间编译和运行。然后如何恢复这些对象(在编译时创建)?
醇>
常量 存储在已编译的文件中。因此,只要JVM决定加载此类,它们就可以检索。
- 当我们实习一个字符串时会发生什么。
醇>
对一系列字符串执行
String.intern()
将确保具有相同内容的所有字符串共享相同的内存