什么时候Javastring被拦截?

受到这个问题的评论的启发,我非常确定,Java String是在运行时执行的,而不是编译时间 – 当然只是类可以在不同时间编译的事实,但在运行时仍然指向相同的引用。

我似乎无法find任何证据来支持这件事。 任何人都可以certificate这一点?

在两个地方进行优化(或者至less可以发生):

  • 如果两个引用相同的string常量出现在同一个类,我希望类文件只包含一个常量池条目。 为了确保在JVM中只创build一个String对象,这并不是严格要求的,但这是一个明显的优化。 这实际上并不是实习生 – 只是不断的优化。
  • 当类加载时,类的string池被添加到内部池中。 这是“真正的”实习。

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

编辑:JVM规范的第5.1节“运行时常量池”进入详细信息:

为了派生string文字,Java虚拟机检查由CONSTANT_String_info结构给出的字符序列。

  • 如果方法String.intern先前在包含与CONSTANT_String_info结构相同的Unicode字符序列的String类实例上调用,则string文字派生的结果是对同一个类String实例的引用。

  • 否则,将创build一个包含由CONSTANT_String_info结构给出的Unicode字符序列的类String的新实例; 该类实例是string文字派生的结果。 最后,调用新的String实例的intern方法。

运行。

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

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

types为String的编译时常量expression式始终是“interned”的,以便使用方法String.intern共享唯一的实例。

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

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

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

这里没有编译时间的贡献,禁止价值恒定的香草。