Java Strings何时实施?

时间:2010-08-10 16:23:07

标签: java string

受到this question上的评论的启发,我很确定Java String是在运行时而不是编译时间实现的 - 当然,事实上可以在不同的时间编译类,但是仍然会在运行时指向相同的引用。

我似乎无法找到任何证据支持这一点。有人可以证明这一点吗?

2 个答案:

答案 0 :(得分:17)

优化在两个地方都会发生(或至少可能发生):

  • 如果对同一个字符串常量的两个引用出现在同一个类中,我希望该类文件只包含一个常量池条目。这不是严格必需的,以确保在JVM中只创建一个String对象,但这是一个明显的优化。这实际上不是实习生 - 只是不断优化。
  • 加载类时,类的字符串池将添加到实习池中。这是“真正的”实习。

(我有一个模糊的回忆,Java 7围绕“小jar文件”的一部分工作包括整个jar文件的单个字符串池......但我可能是非常错误的。)

编辑:JVM规范的第5.1节,"The Runtime Constant Pool"详细说明了这一点:

  

要派生字符串文字,Java   虚拟机检查序列   由...给出的字符   CONSTANT_String_info结构。

     
      
  • 如果String.intern方法有   以前在一个实例上调用过   包含序列的String类   与...相同的Unicode字符   由CONSTANT_String_info给出的   结构,然后是字符串的结果   字面派生是一个参考   类String的相同实例。

  •   
  • 否则,是一个新的类实例   创建包含的字符串   给出的Unicode字符序列   通过CONSTANT_String_info结构;   该类实例是结果   字符串文字推导。最后,   新String的实习方法   调用了实例。

  •   

答案 1 :(得分:0)

运行系统。

JLS和JVM规范将javac编译指定为类文件,这些类文件包含常量声明(在常量池中)和代码中的常量用法(javac可以作为基元/对象引用值内联)。对于编译时字符串常量,编译器生成用于构造String实例的代码并为它们调用String.intern(),以便JVM自动实现字符串常量。这是来自JLS的行为要求:

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28

  

类型为String的编译时常量表达式总是“实例化”,以便使用String.intern方法共享唯一的实例。

但是这些规范既没有概念,也没有任何特定String intern池结构/引用/句柄的定义,无论是编译时还是运行时。 (当然,一般来说,JVM规范并没有要求对象的任何特定内部结构:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.7

没有提到实习池结构的原因是因为它们完全使用String类处理。实习池是String类的私有静态/类级结构(未由JLS和JVM规范& javadoc指定)。

在运行时调用String.intern()时,会将对象添加到实习池中。实体池由String类私有使用 - 当代码创建新的String实例并调用String.intern()时,String类确定是否重用现有的内部数据。优化可以由JIT编译器在运行时执行。

这里没有编译时贡献,禁止内联常量值。