什么是 Java 中的常量池?

Sherwin.Wei Lv8

什么是 Java 中的常量池?

回答重点

Java 中的常量池(Constant Pool)是一块存储用于运行时的常量或符号的区域。它主要存在于两种地方:

  • 运行时常量池:在每个类或接口的 Class 文件中存储编译时生成的常量信息,并在类加载时进入 JVM 方法区(Java 8 之后是 metaspace)。
  • 字符串常量池:用于存储字符串字面量,位于堆内存中的一块特殊区域。通过 String 类中的 intern() 方法可以将字符串加入到字符串常量池。

常量池的作用

  • 常量池主要用于减少重复对象的创建,节省内存并提高效率。在 Java 编译过程中,一些常用的常量值如字符串、基本类型等会存储在常量池中,避免重复创建相同的常量。

扩展知识

字符串常量池与堆内存

字符串常量池最具代表性。在 Java 中,字符串的创建方式有两种:

  • 直接使用字面量String s = "Hello"; 会将 "Hello" 存储在常量池中,如果常量池中已存在 "Hello",则不会重复创建。
  • 使用 new 关键字String s = new String("Hello"); 不论常量池中是否已存在"Hello",都会在堆中创建一个新的 String 对象。

常量池的存储内容

常量池不仅存储字符串常量,还包括:

  • 基本类型的字面量(如整数、浮点数)
  • 类和接口的引用
  • 方法和字段的符号引用(用于动态链接)

intern() 方法

String.intern() 方法会将字符串加入到字符串常量池中,如果池中已存在该字符串,则返回池中的引用。如果没有,则将当前字符串添加到池中。

1
2
3
String str1 = new String("abc");
String str2 = str1.intern();
System.out.println(str1 == str2); // false

Java 1.6 和 1.7 关于常量池的差异

在 Java 1.7 的时候,HotSpot 将字符串从运行时常量池(方法区内)中剥离出来,搞了个字符串常量池存储在堆内,因为字符串对象也经常需要被回收,因此放置到堆中好管理回收。

企业微信截图_fd863e4d-646b-4b69-8c91-ead9144b9f07.png

不过按照 Java 虚拟机定义而言,字符串常量池还是属于运行时常量池,只不过 HotSpot 的实现将其放在里堆中而已,逻辑上它还是属于运行时常量池。

Comments