JVM体系结构:Method区域中的运行时常量池是每个类

时间:2016-11-16 19:21:33

标签: java jvm

通过阅读Oracle JVM体系结构文档:

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html

  

运行时常量池是每个类或每个接口的运行时   在类文件中表示constant_pool表(第4.4节)。

我理解,对于每个,它都有一个运行时常量池(如果我错了,请纠正我)。

然而,我感到困惑的是,如果我有两个不同的类A和B,并且每个类都有一个私有String变量,请说String value = "abc"

如果我使用A.value而不是B.value==equals进行比较,我会得到一个true让我认为"abc" A和B都在同一个运行时常量池中?有人能指出我错在哪里吗?

2 个答案:

答案 0 :(得分:3)

这是JLS叠加的抢先优化。

来自JLS 7, §3.10.5(格式化我的)

  

此外,字符串文字始终引用类String的同一实例。这是因为字符串文字 - 或者更一般地说,字符串是常量表达式(§15.28)的值 - 是" interned"以便使用String.intern方法共享唯一实例。

但请注意,这仅适用于字符串文字和常量表达式。动态构造的字符串(例如,x + yx的{​​{1}}不会自动实现,以共享相同的唯一实例。因此,除非您可以保证操作数是常量表达式,否则您仍然必须使用y

答案 1 :(得分:1)

这是因为' =='是比较参考。 A和B的对象都有不同的String值变量(因此每个类'常量池都有一个单独的条目);但它们都被初始化为相同的值。编译器/ JVM很可能通过使它们都指向字节码中的相同编译时常量值来优化空间。 ' =='运算符不是比较常量池位置。

编辑:为了消除一些困惑,这并不意味着" =="可用于字符串比较。我所说的只是它不能用于比较常量池位置。这只是一件事,一件事:比较两个引用是否指向同一个对象。问题中的情况有时会导致==返回true,但有时不会。这取决于编译器和JVM做出的决定(或者取决于JSL作为精明的回答者所说的内容)。