侧边栏壁纸
博主头像
月伴飞鱼 博主等级

行动起来,活在当下

  • 累计撰写 126 篇文章
  • 累计创建 31 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录
JVM

什么是Class常量池,和运行时常量池关系是什么?

月伴飞鱼
2025-03-21 / 0 评论 / 1 点赞 / 11 阅读 / 0 字
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

1. Class 常量池(Class Constant Pool)

Class 常量池Class 文件中的资源仓库,用于存储 编译期生成的字面量(Literal)和符号引用(Symbolic References)
它是 Java 字节码的一部分,用于支持类加载和运行时解析。

Class 常量池存储的内容

  • 字面量(Literal)

    • 基本类型常量(如 intfloat

    • 字符串常量(如 "Hello"

  • 符号引用(Symbolic References)

    • 类和接口的全限定名

    • 字段名称和描述符

    • 方法名称和描述符

    • 接口方法的引用

Class 常量池的特点

  • 存储在 .class 文件中,在编译时生成。

  • 是方法区的一部分,但不同 JDK 版本的存储方式不同。

  • 在类加载时被 JVM 解析,用于支持方法解析、动态绑定等。

2. 运行时常量池(Runtime Constant Pool)

运行时常量池JVM 方法区的一部分,它在 类加载时Class 常量池 解析并存储 实际的常量值和引用

运行时常量池的作用

  • 存储 Class 常量池解析后的内容

  • 支持动态常量

  • 支持 String.intern()

  • 可在运行时动态修改

运行时常量池与 Class 常量池的关系

  1. Class 常量池运行时常量池

    • 当类加载时,JVM 解析 .class 文件,将 Class 常量池的数据加载到运行时常量池中。

  2. 运行时常量池支持动态添加

    • 运行时常量池不仅包含 .class 中的常量,还支持运行时动态添加,如 String.intern()

3. 运行时常量池存储位置的变化

JDK 版本

运行时常量池存储位置

特点

JDK 1.6 及之前

永久代(PermGen)

容量有限,容易 OOM

JDK 1.7

常量池从永久代移到堆

String.intern() 存在堆中

JDK 1.8 及之后

常量池存放在 Metaspace

使用本地内存,避免 OOM

4. 如何查看 Class 常量池

可以使用 javap -v 命令反编译 .class 文件,查看 Class 常量池内容。

javap -v HelloWorld.class

示例输出:

Constant pool:
   #1 = Methodref  #6.#15    // java/lang/Object."<init>":()V
   #2 = Class      #16       // HelloWorld
   #3 = Utf8       HelloWorld
   #4 = Utf8       main
   #5 = Utf8       ([Ljava/lang/String;)V
   #6 = Class      #17       // java/lang/Object
   #7 = Utf8       java/lang/Object
   #8 = Utf8       Code
   #9 = Utf8       LineNumberTable
  #10 = Utf8       SourceFile
  #11 = Utf8       HelloWorld.java
  • #1 = Methodref #6.#15:表示方法引用,指向 Object.<init>()

  • #3 = Utf8 HelloWorld:存储类名 HelloWorld

  • #6 = Class #17:表示 java/lang/Object 的符号引用。

5. 运行时常量池的作用

(1) 字符串常量池

String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2);  // true
  • "hello" 被存储在 运行时常量池s1s2 指向同一对象。

(2) String.intern()

String s1 = new String("hello").intern();
String s2 = "hello";
System.out.println(s1 == s2);  // true
  • intern() 方法会检查运行时常量池,如果已存在相同的字符串,则返回池中的引用。

6. 总结

概念

存储位置

作用

Class 常量池

.class 文件

编译时存储字面量 & 符号引用

运行时常量池

方法区(JDK 1.6 及之前为永久代,JDK 1.7+ 为堆或 Metaspace)

运行时解析 Class 常量池,支持 String.intern()

  • Class 常量池是 Class 文件的一部分,存储编译期的常量

  • 运行时常量池加载 Class 常量池,并允许动态添加

  • JDK 1.7 及之后,运行时常量池被移至堆或 Metaspace,避免 PermGen OOM

公众号.png

1
JVM
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
    1. 支付宝打赏

      qrcode alipay
    2. 微信打赏

      qrcode weixin
博主关闭了所有页面的评论