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