Java Strings 何时被拘禁?
受到对这个问题的评论的启发,我很确定Java是在运行时而不是编译时被禁产的 - 当然只是类可以在不同的时间编译,但仍然会在运行时指向相同的引用。String
我似乎找不到任何证据来支持这一点。任何人都可以证明这一点吗?
受到对这个问题的评论的启发,我很确定Java是在运行时而不是编译时被禁产的 - 当然只是类可以在不同的时间编译,但仍然会在运行时指向相同的引用。String
我似乎找不到任何证据来支持这一点。任何人都可以证明这一点吗?
优化发生在两个地方(或者至少可能发生):
String
(我有一个模糊的记忆,Java 7围绕“小jar文件”的工作之一包括整个jar文件的单个字符串池......但我可能大错特错了。
编辑:JVM规范的第5.1节“运行时常量池”详细介绍了以下内容:
为了派生字符串文本,Java 虚拟机会检查CONSTANT_String_info结构给出的字符序列。
如果以前在类 String 的实例上调用了方法 String.intern,该实例包含与CONSTANT_String_info结构给出的 Unicode 字符序列相同的 Unicode 字符序列,则字符串文本派生的结果是对类 String 的同一实例的引用。
否则,将创建一个类 String 的新实例,其中包含由 CONSTANT_String_info 结构给出的 Unicode 字符序列;该类实例是字符串文本派生的结果。最后,调用新 String 实例的 intern 方法。
运行。
JLS和JVM规范将javac编译指定为类文件,其中包含常量声明(在常量池中)和代码中的常量用法(javac可以内联为基元/对象引用值)。对于编译时 String 常量,编译器生成代码来构造 String 实例并为它们调用 String.intern(),以便 JVM interns String 常量自动执行。这是JLS的行为要求:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28
String 类型的编译时常量表达式始终是“暂存”的,以便使用方法 String.intern 共享唯一实例。
但是这些规范既没有概念,也没有定义任何特定的字符串实习池结构/引用/句柄,无论是编译时还是运行时。(当然,一般来说,JVM规范并不要求对象有任何特定的内部结构:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.7)
未提及实习生池结构的原因是,它们完全使用 String 类进行处理。实习生池是 String 类的私有静态/类级结构(JLS & JVM specs & javadoc 未指定)。
在运行时调用 String.intern() 时,对象将添加到实习生池中。String 类私下利用了实习生池 - 当代码创建新的 String 实例并调用 String.intern() 时,String 类确定是否重用现有的内部数据。优化可以由 JIT 编译器在运行时执行。
这里没有编译时贡献,禁止常量值的香草内联。