概述
当我们编译一个.java文件的时候,我们得到一个扩展名为.class的独立类文件。这个类文件是由几部分组成的,常量池就是其中的一部分。
简单的说,常量池包含运行类所需要的所有常量。基本上,它是一个类似于符号表的运行时数据结构。
常量池的内容是由编译器生成的符号引用组成的。这些引用是代码中引用的变量、方法、接口及类的名称。JVM使用它们将代码与它依赖的其他类进行链接。
我们编写来编写一个很简单的程序,来查看一下常量池:
public class MethodAreaApplication {
public static void main(String[] args) throws Exception {
System.out.println("starting...");
}
}
查看使用maven或javac编译后的.class文件:
javap -v com/dokdok/lession/methodarea/MethodAreaApplication.class
其输出的结果如下:

#n 指出常量池的引用。例如#14是一个对“starting…”的符号引用。
从图中我们可以看出,其中包括所有class、String、out等关键字。图中红色的框中,就是我们打印的starting…的文件部分(其中的#14就是其实际文本内容)。我们看到它是以常量的方式存放在常量池中,这就是为什么我们在编程的过程中不建议直接使用String类型的变量存放过长的字面值(文本),因为它会过多占用方法区的空间(因为常池就是存放在方法区)。
常量池支持的几种类型
- Integer
- Double
- String:一个16bit的字符串常量,用于指向常量池中所包含的实际内容的其他条目
- Class:包含完全限定的类名
- Utf8:字节流
- NameAndType:由冒号分隔的值对,第一个条目表示名称,第二个条目指表示类型
- Fieldref、Methodref、InterfaceMethodref:由逗号隔开的值对,第一个值指向class的条目,而第二个值指向NameAndType的条目
- 其他类型如boolean、short以及byte等,它们在常量池中表示为Integer常量