首页 文章

使用String文字编译器行为来创建字符串常量池

提问于
浏览 1329
0

阅读完这些讨论后question 1question 2article

我对 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引用 .

enter image description here

Line 2: 编译器在字符串常量池中搜索对象"xyz"的任何现有引用 . 但是找不到一个 . 因此,它创建对象"xyz"并将其引用放在String Constant Pool中 .

enter image description here

Line 3: 这次编译器在String Constant Pool中找到对象,并且不在池或堆中创建任何其他条目 . 变量 c 仅引用现有对象,该对象也由 a 引用 .

enter image description here

Line 4: 第4行中的文字出现在字符串常量池中 . 因此,不再在游泳池中进入 . 但是在运行时,为"abc"创建了另一个String对象,其引用存储在变量 d 中 .

enter image description here

现在我有以下问题/疑问:

  • 上面描述的是什么?

  • 编译器如何创建对象?据我所知,对象是在运行时创建的,而堆是运行时内存区域 . 那么,在编译时如何以及在何处创建String对象!

  • 源代码可以在一台机器上编译,并在不同的机器上运行 . 或者,即使在同一台机器上,它们也可以在不同的时间编译和运行 . 然后如何恢复这些对象(在编译时创建)?

  • 当我们实习一个字符串时会发生什么 .

1 回答

  • 1

    这究竟发生了什么,如上所述?

    是的,但从概念上讲,常量池和字符串池是不同的东西 .

    constant pool.class 文件的一部分,该文件包含此类中使用的所有常量 .

    string pool是运行时概念 - 实习字符串和字符串文字are stored here .

    这是常量池上的JVM specification . 它是 .class 格式部分的一部分 .

    编译器如何创建对象?据我所知,对象是在运行时创建的,而堆是运行时内存区域 . 那么,在编译时如何以及在何处创建String对象!

    我相信,如何/恰当发生这种情况是一个特定于JVM实现的细节(如果我错了,请纠正我),但基本的解释是每当JVM决定加载一个类时, constant pool 中找到的任何字符串都会被自动放置进入运行时 string pool ,并使任何重复项引用同一个实例 .

    在其中一个链接答案的评论中,Paŭlo Ebermann says

    当在VM中加载类时,字符串常量将被复制到堆,到VM范围的字符串池

    所以看来这至少是Sun的VM如何实现字符串池 .

    在JDK 7 / HotSpot之前,实习字符串存储在permanent generation space中 - 现在它们存储在主堆中 .

    源代码可以在一台机器上编译,并在不同的机器上运行 . 或者,即使在同一台机器上,它们也可以在不同的时间编译和运行 . 然后如何恢复这些对象(在编译时创建)?

    常量存储在已编译的文件中 . 因此,只要JVM决定加载此类,它们就是可检索的 .

    当我们实习一个String时会发生什么 .

    这是answered here

    对一系列字符串执行String.intern()将确保具有相同内容的所有字符串共享相同的内存

相关问题