java - 使用字符串文字创建字符串常量池的编译器行为

标签 java string memory-management compilation heap-memory

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

我对Java字符串常量池的理解如下(如有错误请指正):

当源代码被编译时,编译器在我们的程序中寻找所有的字符串文字(那些被放在双引号中的)并在堆区域中创建不同的(没有重复的)对象并在一个特殊的内存区域中维护它们的引用称为字符串常量池(方法区内的区域)。任何其他字符串对象都是在运行时创建的。

假设我们的代码有如下语句:

String a = "abc";                  //Line 1
String b = "xyz";                  //Line 2
String c = "abc";                  //Line 3
String d = new String("abc"):      //Line 4

当编译上面的代码时,

第 1 行:在堆中创建了一个字符串对象“abc”,该对象被变量a 和字符串常量池引用。

enter image description here

第 2 行:编译器在字符串常量池中搜索对对象“xyz”的任何现有引用。但没有找到一个。因此,它创建对象“xyz”并将其引用放入字符串常量池中。

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. Is that what happens exactly which is described above?

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

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

string pool是一个运行时概念 - 内部字符串和字符串文字 are stored here .

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

  1. How does the compiler creates object? As per my knowledge, objects are created at Run time and heap is a Run time memory area. So, how and where does String objects are created at the time of compilation!

如何/何时发生这种情况,我相信,这是 JVM 实现特定的细节(如果我错了请纠正我),但基本的解释是每当 JVM 决定加载一个类时, 在 constant pool 中找到的任何字符串都会自动放入 runtime string pool 中,并且任何重复的字符串都指向同一个实例。

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

when the classes are loaded in the VM, the string constants will get copied to the heap, to a VM-wide string pool

看来这至少是 Sun 的 VM 实现字符串池的方式。

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

  1. Source code can be compiled in one machine and run in a different machine. Or, even in the same machine they can be compiled and run in different time. Then how those objects (created in compile time) are recovered?

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

  1. What happens when we intern a String.

这是 answered here :

doing String.intern() on a series of strings will ensure that all strings having same contents share same memory

关于java - 使用字符串文字创建字符串常量池的编译器行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48213869/

相关文章:

java - Wicket 口可见性和类别切换

java - 为什么当我的应用程序关闭时,我必须双击通知才能将其关闭?

javascript - 将字符串转换为 javascript 关联数组

regex - 替换文件中的标记时的 Groovy 正则表达式

c++ - SWIG 无法识别字符串参数

java - 跟踪资源并在不需要时卸载它们

java - 在java中加密文本文件的最简单方法

java - 如何在 Android 上没有任何 TextView 的情况下在字符串上使用自定义字体样式

objective-c - for循环中的 objective-c 内存管理

java - 当 Java 应用程序以 block 的形式读取巨大文件时减少内存占用