Java 常量池的目的是什么?

我目前正试图深入研究 Java 虚拟机的规范。我一直在阅读 在 JVM 联机书中,有一个令人困惑的抽象概念我似乎无法理解: ConstantPool。以下是这本书的节选:

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

我有几个关于上述和一般 CP 的问题:

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

用简单的英语说,恒定池的目的是什么?

CP 是一个存储区域,存储非常独特的常量值以减少冗余:

System.err.println("Hello");
System.out.println("Hello");

在 CP 中只有一个 String 对象“ Hello”,编译器在两行中替换同一个引用。你的。类文件只包含一个 Hello 字符串。(其他类型也一样)。

CP 是否位于每种类型的.Class 文件中?

是的,看这里: http://en.wikipedia.org/wiki/Java_class_file

常量池是包含运行该类代码所需常量的 .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)方法的符号引用。

正如您所看到的,符号引用不仅仅是名称——例如,对方法的符号引用还包含有关其参数(Ljava/lang/String;)和返回类型(V表示 void)的信息。

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

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

enter image description here

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

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

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

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

这里有一个链接到 JVM 内部的更多细节。

让我们先举例子来理解字符串常量池的含义

   public class StringConstantPool {
public static void main(String[] args) {
String s = "prasad";
String s2 = "prasad";
     

System.out.println(s.equals(s2));
System.out.println(s == s2);
}
}

输出将是

true


true

这里发生了什么一步一步

1-在调用 JVM 时加载该类。

2-JVM 将在程序中查找所有的字符串文字。

首先,它找到指向字面 “ Prasad”变量 s ,然后在内存中创建它

4-字面 “ Prasad”的引用将放置在字符串常量池内存中。

然后它找到另一个引用相同字符串文字 Prasad< strong > 变量 s2

既然 JVM 已经找到了字符串文字 Prasad,那么两个 变量 s 和 s2都将引用同一个对象,即 Prasad

enter image description here

希望这对你有帮助

继续读 Http://www.journaldev.com/797/what-is-java-string-pool

它可能被解释为浏览器的浏览历史记录,从而减少每次查找或构建的需要