当前位置: 首页 > 知识库问答 >
问题:

JVM架构:方法区域中的运行时常量池是每个类

谢洛城
2023-03-14

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

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

运行时常量池是类文件中常量池表的每类或每接口运行时表示形式(§4.4)。

我知道每个类都有一个运行时常量池(如果我错了,请纠正我)。

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

如果我用=而不是等于来比较A.valueB.value,我会得到一个true,这让我觉得A和B中的“abc”都在同一个运行时常量池中?有人能指出我错在哪里吗?


共有2个答案

高云瀚
2023-03-14

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

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

燕光熙
2023-03-14

这是JLS叠加的先发制人优化。

来自JLS 7第3.10.5节(格式)

此外,字符串文本总是引用类String的相同实例。这是因为字符串文本——或者更一般地说,作为常量表达式值的字符串(§15.28)——被“内嵌”,以便使用方法String.intern共享唯一实例。

但是,请注意,这仅适用于字符串文字和常量表达式。动态构造的字符串(例如,字符串xyxy)不会自动插入以共享相同的唯一实例。因此,您仍然必须使用。通常等于,除非可以保证操作数是常量表达式。

 类似资料:
  • 什么是运行时常量池和java中的方法区。我读到JVM创造了这两个,但是哪一个是第一个存在的?还有它们包含什么?任何帮助将不胜感激。

  • 根据以下链接,java堆栈框架包含本地变量、操作数堆栈和当前类常量池引用。http://blog.jamesdbloom.com/JVMInternals.html 同样来自Oracle“JVM结构”第2.6节。3.“动态链接-每个帧(§2.6)包含对当前方法类型的运行时常量池(§2.5.5)的引用,以支持方法代码的动态链接。” 我还读到堆中的对象也有一个指向类数据的指针/引用。https://w

  • 如果我在Jasmin assembly中创建一个新项目,然后将其存储,我会按照指令aload进行操作,因为它是一个地址: 现在,如果我想从常量池中保存一个字符串...我会用ldc创建它,然后用aload保存它: 现在...这些地址是否在相同的形式和相同的字节数上?因为我使用相同的指令来加载和存储这些项目,JVM必须能够区分属于常量池的地址和堆中的地址? 在检查字节码时,在我的例子中,常量池中的实际

  • 我正在我的Java SSE(Java Flex)应用程序中使用Quartz Scheduler 2.2.0。我设定了一个时间表,每天上午10点运行,并执行一些工作。我没有关闭Quartz调度程序,因为我想让它每天运行。 但无论如何,我知道Quartz调度程序已经在运行,因为如果我在用户打开Java Flex应用程序时启动它,那么就会有多个实例存在。 Quartz.Properties 这就是我安排

  • 主要内容:本地方法栈本地方法栈 Java虚拟机栈用于管理Java方法的调用,而本地方法栈用于管理本地方法的调用 本地方法栈,也是线程私有的。 允许被实现成固定或者是可动态拓展的内存大小。(在内存溢出方面是相同的) 如果线程请求分配的栈容量超过本地方法栈允许的最大容量,Java虚拟机将会抛出一个StackOverFlowError异常。 如果本地方法栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新

  • 问题内容: 我必须对一个大型Java项目做一个一般性的说明,但是我对它的了解很少,我想知道是否有确定以下内容的准则: 每个包有多少个类可以被认为是正确的,低或高的(这个项目每个包有3.89个类,对我来说似乎太小了), 每个类有多少种方法?(该项目每个类有6.54个方法… 每个方法的行数?(此项目每种方法大约有7行(对我来说似乎不错,也许有点低)) 我应该指出,这个问题仅涉及体积。我有很多来自质量工