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

时间:2018-01-11 18:40:43

标签: java string memory-management compilation heap-memory

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

我对 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 和字符串常量池引用。

enter image description here

第2行:编译器在字符串常量池中搜索对象" xyz"的任何现有引用。但是找不到一个。所以,它创造了对象" xyz"并将其引用放在String Constant Pool中。

enter image description here

第3行:这次编译器在字符串常量池中找到对象,并且不在池或堆中创建任何其他条目。变量 c 仅指现有对象,也由 a 引用。

enter image description here

第4行:第4行中的文字出现在字符串常量池中。因此,不再在游泳池中进入。然而,在运行时,为" abc"创建了另一个String对象。其参考文献存储在变量 d

enter image description here

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

  1. 上面描述的具体是什么?
  2. 编译器如何创建对象?根据我的知识,对象 在运行时创建,堆是运行时内存区域。又怎样 以及何时创建String对象 编译!
  3. 源代码可以在一台机器上编译,也可以在不同的机器上运行 机。或者,即使在同一台机器上,也可以编译和运行它们 不同的时间。那么这些对象(在编译时创建)是怎样的 回收
  4. 当我们实习一个字符串时会发生什么。

1 个答案:

答案 0 :(得分:1)

  
      
  1. 上面描述的具体是什么?
  2.   

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

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

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

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

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

如何/当完全这种情况发生时,我相信,这是一个特定于JVM实现的细节(如果我错了,请纠正我),但基本的解释是每当JVM决定加载一个类时,常量池中找到的任何字符串都会自动放入运行时 字符串池中,并且可以使用任何重复项来引用同一个实例。

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

  

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

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

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

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

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

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

这是answered here

  

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