讲师中心 微信公众号

工具推荐

视频效率加速
updream

一键生成高质量推广成片

Seko
Seko

AI短剧一键生成成片

剧云
剧云

中文短剧剧本制作平台

立刻MV
立刻MV

低成本歌曲 MV、视频生成

在Java中运行时常量池如何理解_Java常量池原理解析

梦丽姑娘_8143

梦丽姑娘_8143

发布时间:2026-01-29 06:39:28

|

707人浏览过

|

来源于php中文网

原创

运行时常量池是每个类独有的编译期快照,位于方法区(JDK 8+为元空间),存储字面量和符号引用,支持有限动态扩充,与字符串常量池协同工作但不等同。

在java中运行时常量池如何理解_java常量池原理解析

运行时常量池是每个类独有的“编译期快照”

运行时常量池不是全局共享的内存池,而是每个类在加载进JVM后,在方法区(JDK 8+ 是元空间)中生成的一份独立副本——它本质是 class 文件常量池内容的运行时映射。你写一个 MyClass,JVM 就为它建一个专属的运行时常量池;再写个 YourClass,又建另一个。它们互不干扰。

  • 它存的是编译期确定的字面量(如 "abc"、123、true、final int x = 42)和符号引用(如 java/lang/String、"toString()Ljava/lang/String;")
  • 这些内容在类加载的「解析阶段」才被逐步转成直接引用(比如把类名字符串变成指向 Class 对象的指针)
  • 它支持动态扩充:调用 String.intern()、反射生成的类名等,都可能往当前类的运行时常量池里塞新项(注意:不是所有 JVM 实现都允许任意扩充,HotSpot 对非字符串类的动态添加限制较严)

字符串常量池 ≠ 运行时常量池,但两者深度联动

字符串常量池(StringTable)是全局唯一的哈希表,位于堆内存(JDK 7+),而运行时常量池是每个类一份、位于元空间。但二者在字符串处理上紧密协作:

  • 当你写 String s = "hello",JVM 先查字符串常量池是否有 "hello" 的引用;若有,直接返回;若无,先在堆中创建对象,再将该对象引用存入字符串常量池
  • 这个过程会**触发对当前类运行时常量池中对应 CONSTANT_String_info 项的解析**:它原本只存着一个指向 CONSTANT_Utf8_info 的索引,此时才真正关联到堆里的字符串实例
  • 所以 s == "hello" 为 true,靠的不是运行时常量池本身存储对象,而是它驱动了字符串常量池的复用逻辑

别误以为 final static 就一定进运行时常量池

只有**编译期可确定值的 static final 基本类型或字符串**才会被“内联”进运行时常量池,并在字节码中被直接替换为常量值;其他情况只是普通静态字段。

javascript-typescript-typescript-scaffold
javascript-typescript-typescript-scaffold

你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型

下载
public class PoolTest {
    public static final int A = 100;           // ✅ 编译期常量,字节码中直接出现 100
    public static final Integer B = 200;       // ❌ 包装类,不内联,运行时从静态变量取值
    public static final String C = "ok";       // ✅ 字符串字面量,进字符串常量池,也关联运行时常量池
    public static final String D = new String("no"); // ❌ new 出来,不进字符串常量池,也不触发运行时常量池内联
}
  • 反编译看 javap -v PoolTest.class,你会发现只有 A 和 C 出现在常量池表中,且 A 的使用位置直接是 bipush 100
  • B 和 D 虽然也是 final,但因无法在编译期确定(后者甚至涉及运行时对象创建),不会进入运行时常量池,也不会带来复用收益

运行时常量池溢出的真实风险点

运行时常量池本身不常爆内存,但它的膨胀往往暴露底层问题:大量动态生成类(如反复 ASM 或 CGLIB 代理)、滥用 intern() 处理长生命周期字符串、或反射频繁注册新符号,都可能导致元空间(Metaspace)耗尽,抛出 java.lang.OutOfMemoryError: Metaspace。

立即学习“Java免费学习笔记(深入)”;

  • 监控建议:加 JVM 参数 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps,观察 Metaspace 使用趋势
  • 调优重点不是扩大 -XX:MaxMetaspaceSize,而是检查是否在循环中调用 String.intern() 处理未去重的用户输入(比如日志字段、HTTP header 值)
  • JDK 8+ 中,StringTable 默认大小仅 1009 个桶,高并发 intern 可能引发哈希冲突激增,必要时用 -XX:StringTableSize=65536 扩容

最易被忽略的是:运行时常量池的“懒解析”特性——某些符号引用直到第一次被调用才解析,这意味着 OOM 可能延迟出现在看似无关的代码路径上,而非类加载瞬间。

热门AI工具

更多
花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

7519

2023.08.02

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6384

2023.10.24

字符串常量的表示方法
字符串常量的表示方法

字符串常量的表示方法:1、使用引号;2、转义字符;3、多行字符串;4、原始字符串;5、字符串连接;6、字符串字面量和对象;7、编码问题。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1183

2023.12.26

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1938

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

3184

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6384

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

6549

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

8094

2024.03.22

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

20

2026.11.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn