1.简介
编译.java
文件时,会得到一个扩展名为.class
的单独的类文件。 .class
文件由几个部分组成,并且常量池就是其中之一。
在本快速教程中,我们将探讨常量池的详细信息。另外,我们将看到它支持什么类型以及如何格式化信息。
2. Java中的常量池
简而言之,常量池包含运行特定类的代码所需的常量。基本上,它是类似于符号表的运行时数据结构。它是Java类文件中每个类或每个接口的运行时表示形式。
常量池的内容由编译器生成的符号引用组成。这些引用是从代码引用的变量,方法,接口和类的名称。 JVM使用它们将代码与它其他依赖的类链接。
让我们使用一个简单的Java类来了解常量池的结构:
public class ConstantPool {
public void sayHello() {
System.out.println("Hello World");
}
}
要查看常量池的内容,我们需要首先编译文件,然后运行以下命令:
javap -v name.class
上面的命令将产生:
#1 = Methodref #6.#14 // java/lang/Object."<init>":()V
#2 = Fieldref #15.#16 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #17 // Hello World
#4 = Methodref #18.#19 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #20 // com/baeldung/jvm/ConstantPool
#6 = Class #21 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 sayHello
#12 = Utf8 SourceFile
#13 = Utf8 ConstantPool.java
#14 = NameAndType #7:#8 // "<init>":()V
#15 = Class #22 // java/lang/System
#16 = NameAndType #23:#24 // out:Ljava/io/PrintStream;
#17 = Utf8 Hello World
#18 = Class #25 // java/io/PrintStream
#19 = NameAndType #26:#27 // println:(Ljava/lang/String;)V
#20 = Utf8 com/baeldung/jvm/ConstantPool
#21 = Utf8 java/lang/Object
#22 = Utf8 java/lang/System
#23 = Utf8 out
#24 = Utf8 Ljava/io/PrintStream;
#25 = Utf8 java/io/PrintStream
#26 = Utf8 println
#27 = Utf8 (Ljava/lang/String;)V
#n
表示对常量池的引用。 #17是对“Hello World” String
的符号引用,#18是System.out
,而#19是println.
同样,
#8强调方法的返回类型为void
而#20为完全限定的类名。
重要的是要注意,常量池表从索引1开始。索引值0被视为无效索引。
2.1。种类
常量池支持几种类型:
-
Integer
,Float
:具有32位常量 -
Double
,Long
:具有64位常量 -
String
:一个16位的字符串常量,指向池中包含实际字节的另一个条目 -
Class
:包含完全限定的类名称 -
Utf8
:字节流 -
NameAndType
:冒号分隔的一对值,第一个条目表示名称,第二个条目表示类型 -
Fieldref
,Methodref
,InterfaceMethodref
:点分隔的一对值,第一个值指向Class
条目,而第二个值指向NameAndType
条目
那么其他类型如boolean
, short
和byte
呢?这些类型在池中表示为Integer
常量。
2.2。格式
表中的每个条目均遵循通用格式:
cp_info {
u1 tag;
u1 info[];
}
最初的1字节标签指示常量的种类。 JVM抓取并拦截标签后,便知道标签后面的内容。通常,标签后跟两个或多个字节,以携带有关该常数的信息。
让我们看一些类型及其标签索引:
-
Utf8
:1 -
Integer
:3 -
Float
:4 -
Long
:5 -
Double
:6 - 班级参考:7
-
String
参考:8
只有在JVM完成加载后,才会创建任何类或接口的常量池。
3.结论
在这篇快速文章中,我们了解了JVM中的常量池。我们已经看到它包含用于定位实际对象的符号引用。此外,我们还将研究常量池如何查看常量池的内容及其类型的信息。
0 评论