Java 常量池的目的是什么?

2022-08-31 12:42:12

我目前正在尝试更深入地研究Java虚拟机的规范。我一直在在线阅读Inside the JVM书籍,有一个令人困惑的抽象,我似乎无法理解:Constant Pool。以下是本书的摘录:

对于它加载的每种类型,Java 虚拟机必须存储一个常量池。常量池是类型使用的一组有序常量,包括文本(字符串、整数和浮点常量)以及对类型、字段和方法的符号引用。常量池中的条目由索引引用,就像数组的元素一样。由于常量池包含对类型使用的所有类型、字段和方法的符号引用,因此常量池在 Java 程序的动态链接中起着核心作用。

我对上述和CP有几个问题:

  1. CP 是否位于每种类型的文件中?.class
  2. 作者所说的“象征性参考”是什么意思?
  3. 恒定池的目的是什么,用简单的英语?

答案 1

常量池是文件(及其内存中表示形式)的一部分,其中包含运行该类的代码所需的常量。.class

这些常量包括程序员指定的文本和编译器生成的符号引用。符号引用基本上是从代码中引用的类,方法和字段的名称。JVM 使用这些引用将代码链接到它所依赖的其他类。

例如,下面的代码

System.out.println("Hello, world!");

产生以下字节码(输出)javap

0:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;              
3:   ldc     #3; //String Hello, world!                                                  
5:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V

#n这是对常量池的引用。 是对字段的符号引用,是字符串,并且是对方法的符号引用。#2System.out#3Hello, world!#4PrintStream.println(String)

如您所见,符号引用不仅仅是名称 - 例如,对方法的符号引用还包含有关其参数 () 和返回类型 ( means ) 的信息。Ljava/lang/String;Vvoid

您可以通过为类运行来检查该类的常量池。javap -verbose


答案 2

我认为理解如何使用图表构建框架会有所帮助。

enter image description here

帧是操作数(操作指令)所在的位置,也是发生动态链接的位置。可以说,这是一种速记方式,使用常量池来跟踪类及其成员。

每个帧都包含对运行时常量池的引用。该引用指向正在为该帧执行的方法类的常量池。此参考有助于支持动态链接。

C/C++代码通常被编译为一个对象文件,然后将多个对象文件链接在一起,以生产一个可用的项目,如可执行文件或 dll。在链接阶段,每个对象文件中的符号引用将替换为相对于最终可执行文件的实际内存地址。在Java中,此链接阶段是在运行时动态完成的。

编译 Java 文件时,对变量和方法的所有引用都作为符号引用存储在类的常量池中。符号引用是逻辑引用,而不是实际指向物理内存位置的引用。

以下是James Blooms JVM Internals的链接,以获取更多详细信息。


推荐