String.intern和JVM有什么关系吗运行-Time Constant pool
Does String.intern has anything to to with JVM Run-Time Constant pool
根据jvms11
,运行-时间常量池中有两种条目:符号引用,稍后可能会解析,以及静态常量,不需要进一步处理. 运行-时间常量池中的静态常量也是根据每个条目的结构从constant_pooltable中的条目派生而来。
我的理解是String.intern和JVM运行-Time Constant pool没有任何关系,但是中国最伟大的程序员之一说String.intern
会“在他的畅销书中 运行time 期间在 运行-Time Constant 池中放入一些东西。我们争论了很久,都无法说服对方
所以我的问题是,String.intern 与 JVM 运行-Time Constant pool 有什么关系吗?
的jvms5.1
The Java Virtual Machine maintains a run-time constant pool for each class and interface (§2.5.5).
术语“for each”的意思是没有一个运行时间常量池,但每个class或接口都有自己的专用池。后面几句更明确了这个数据结构对应的是一个class文件的常量池
The constant_pool
table in the binary representation of a class or interface (§4.4) is used to construct the run-time constant pool upon class or interface creation (§5.3).
应该清楚的是,这个 per-class 结构与用于在整个 运行 时间规范化字符串实例的单一全局数据结构不同。
但是由于 class 文件中字符串常量的所有使用都表示为 class 文件常量池的索引,然后用于构造 class 的 运行-时间常量池,这些使用和全局数据结构有关系。如前所述 within §5.1
The static constants in the run-time constant pool are also derived from entries in the constant_pool
table in accordance with the structure of each entry:
- A string constant is a
reference
to an instance of class String
, and is derived from a CONSTANT_String_info
structure (§4.4.3). To derive a string constant, the Java Virtual Machine examines the sequence of code points given by the CONSTANT_String_info
structure:
- If the method
String.intern
has previously been invoked on an instance of class String
containing a sequence of Unicode code points identical to that given by the CONSTANT_String_info
structure, then the string constant is a reference
to that same instance of class String
.
- Otherwise, a new instance of class
String
is created containing the sequence of Unicode code points given by the CONSTANT_String_info
structure. The string constant is a reference
to the new instance. Finally, the method String.intern
is invoked on the new instance.
正式来说,对应于 class 中使用的字符串常量的 String
实例是 class 的 运行 时间常量池的一部分,但在中初始化String.intern
的条款以确保每个 class 在其池中都有规范化的字符串实例。
但这种关系只有一个方向。当应用程序代码显式调用 String.intern()
时,它不会访问 class 的 运行 时间常量池。甚至不清楚我们应该访问哪个 运行 时间常量池。
所以intern()
与运行时间常量池无关,至少与其他调用者无关。
一个混乱的来源是 JVM 用来实现 intern()
的数据结构在 JVMS 或 JLS 中根本没有名称。所以,没有正式的名字,不同的媒体就会出现不同的名字。例如,API documentation of intern()
表示
A pool of strings, initially empty, is maintained privately by the class String
.
它通常是某种哈希 table,但术语“池”符合其用途,并且由于它存在于 运行 时间,所以人们想出容易混淆的术语也就不足为奇了使用 JVMS §5.1 的 运行-时间常量池。
因此,在开始与其他开发人员进行激烈讨论之前,重要的是要弄清楚,是否每个人都在谈论同一个池。
作为附录,我在上面说过 String
是 正式 运行-time 常量池的一部分,因为这涉及实现的特定方面.
原则上,JVM 可以在创建池时使用 String
个实例初始化 class 的 运行 时间常量池的所有字符串条目。但正如 所证明的那样,广泛使用的 HotSpot JVM 并非如此,它在首次使用时查找或创建 String
实例,而不是 class 初始化时间。
这意味着 运行 时间常量池包含某种形式的原始字符数据,而不是对 String
实例的引用。 String
一旦构造完成,就会被代码引用和重用,但是运行-时间常量池是修改为现在引用String
还是字节码指令(ldc
) 保留它,无法从 Java 应用程序中观察到。我们只能观察到,只要 class 存在,String
实例就不会被垃圾回收。
根据jvms11
,运行-时间常量池中有两种条目:符号引用,稍后可能会解析,以及静态常量,不需要进一步处理. 运行-时间常量池中的静态常量也是根据每个条目的结构从constant_pooltable中的条目派生而来。
我的理解是String.intern和JVM运行-Time Constant pool没有任何关系,但是中国最伟大的程序员之一说String.intern
会“在他的畅销书中 运行time 期间在 运行-Time Constant 池中放入一些东西。我们争论了很久,都无法说服对方
所以我的问题是,String.intern 与 JVM 运行-Time Constant pool 有什么关系吗?
的jvms5.1The Java Virtual Machine maintains a run-time constant pool for each class and interface (§2.5.5).
术语“for each”的意思是没有一个运行时间常量池,但每个class或接口都有自己的专用池。后面几句更明确了这个数据结构对应的是一个class文件的常量池
The
constant_pool
table in the binary representation of a class or interface (§4.4) is used to construct the run-time constant pool upon class or interface creation (§5.3).
应该清楚的是,这个 per-class 结构与用于在整个 运行 时间规范化字符串实例的单一全局数据结构不同。
但是由于 class 文件中字符串常量的所有使用都表示为 class 文件常量池的索引,然后用于构造 class 的 运行-时间常量池,这些使用和全局数据结构有关系。如前所述 within §5.1
The static constants in the run-time constant pool are also derived from entries in the
constant_pool
table in accordance with the structure of each entry:
- A string constant is a
reference
to an instance of classString
, and is derived from aCONSTANT_String_info
structure (§4.4.3). To derive a string constant, the Java Virtual Machine examines the sequence of code points given by theCONSTANT_String_info
structure:
- If the method
String.intern
has previously been invoked on an instance of classString
containing a sequence of Unicode code points identical to that given by theCONSTANT_String_info
structure, then the string constant is areference
to that same instance of classString
.- Otherwise, a new instance of class
String
is created containing the sequence of Unicode code points given by theCONSTANT_String_info
structure. The string constant is areference
to the new instance. Finally, the methodString.intern
is invoked on the new instance.
正式来说,对应于 class 中使用的字符串常量的 String
实例是 class 的 运行 时间常量池的一部分,但在中初始化String.intern
的条款以确保每个 class 在其池中都有规范化的字符串实例。
但这种关系只有一个方向。当应用程序代码显式调用 String.intern()
时,它不会访问 class 的 运行 时间常量池。甚至不清楚我们应该访问哪个 运行 时间常量池。
所以intern()
与运行时间常量池无关,至少与其他调用者无关。
一个混乱的来源是 JVM 用来实现 intern()
的数据结构在 JVMS 或 JLS 中根本没有名称。所以,没有正式的名字,不同的媒体就会出现不同的名字。例如,API documentation of intern()
表示
A pool of strings, initially empty, is maintained privately by the class
String
.
它通常是某种哈希 table,但术语“池”符合其用途,并且由于它存在于 运行 时间,所以人们想出容易混淆的术语也就不足为奇了使用 JVMS §5.1 的 运行-时间常量池。
因此,在开始与其他开发人员进行激烈讨论之前,重要的是要弄清楚,是否每个人都在谈论同一个池。
作为附录,我在上面说过 String
是 正式 运行-time 常量池的一部分,因为这涉及实现的特定方面.
原则上,JVM 可以在创建池时使用 String
个实例初始化 class 的 运行 时间常量池的所有字符串条目。但正如 String
实例,而不是 class 初始化时间。
这意味着 运行 时间常量池包含某种形式的原始字符数据,而不是对 String
实例的引用。 String
一旦构造完成,就会被代码引用和重用,但是运行-时间常量池是修改为现在引用String
还是字节码指令(ldc
) 保留它,无法从 Java 应用程序中观察到。我们只能观察到,只要 class 存在,String
实例就不会被垃圾回收。