String 在内存里到底是怎么存的——我的学习笔记
说在前面前面三篇写完了 JVM 五大区域按计划下一篇应该是垃圾回收。但我学到这里的时候发现有一个绕不开的东西——String 的存储机制。因为学 GC 之前得先知道对象在堆里怎么分配的而 String 又特别典型它既有对象实例在堆里又有字面量在常量池里还牵扯到两个对象还是一个新对象的问题。所以插了一篇专门搞明白 String 到底在内存里是怎么待着的。先问你一个问题Strings1abc;Strings2newString(abc);这两行代码s1 和 s2 指向的是同一个对象吗我之前一直以为是一样的——不都是abc吗结果答案是不一样。s1 指向常量池里的 “abc”s2 指向堆里 new 出来的实例。这个事当时颠覆了我对 String 的认知。这篇就是围绕这个问题展开的。字符串字面量存在哪里先说结论字符串字面量存在字符串常量池里。什么叫字面量就是你在代码里直接写的那些用双引号包起来的字符串比如helloabcJVM 真的很难学这些字符串在编译的时候就会被编译器收进 class 文件的常量池里。等到类加载之后它们会被放到字符串常量池中。常量池的位置变过有一点挺有意思——字符串常量池的位置在 JDK 7 的时候换过一次JDK 版本字符串常量池的位置JDK 6 及之前方法区永久代JDK 7 起堆中为什么要搬因为永久代PermGen的空间是有限且固定的字符串常量池里的字符串太多的话容易把永久代撑爆抛OutOfMemoryError: PermGen space。搬到堆里之后堆空间可以动态扩展而且 GC 也能更好地管理它。new String(abc)到底干了什么这个是我觉得最值得搞明白的地方也是面试常问的题。看这行代码StringsnewString(abc);很多人以为它就创建了一个对象。实际上最多创建了两个对象。我拆一下步骤第一步new 指令在堆里创建一个 String 实例new关键字干的事就是在堆上分配内存创建一个 String 对象。这个对象是空壳——它的值还没有确定。第二步JVM 拿着字面量去常量池里找因为构造方法里传了abc这个字符串字面量JVM 会去字符串常量池里找一找有没有abc这个字符串。这时候有两种情况情况一常量池里之前没有 “abc”那 JVM 就在常量池里创建一个abc对象。这时候就有两个对象了一个是常量池里的abc一个是堆里的new String()实例。后者会引用前者的值。情况二常量池里已经有 “abc” 了那就不创建新的了直接复用已有的。这时候只创建了一个对象——就是堆里那个new String()实例。第三步引用 s 存在当前方法的栈帧里不管创建了几个对象最终s这个引用存在当前方法的栈帧里指向堆里的那个 String 实例不是直接指向常量池里的 “abc”。一张图看清楚栈Stack 堆Heap ┌──────────┐ ┌──────────────────────────┐ │ s (引用) │ ────────→ │ new String(abc) 实例 │ └──────────┘ │ │ │ 字符串常量池堆中 │ │ ┌───────────────────┐ │ │ │ abc 字面量 │ │ │ └───────────────────┘ │ └──────────────────────────┘注意箭头的方向s→new String(abc)实例 → 常量池中的abc作为内部 char[] 引用。那我怎么验证我学的时候写了一段代码验证了一下Strings1abc;Strings2newString(abc);System.out.println(s1s2);// falses1 指向常量池s2 指向堆System.out.println(s1.equals(s2));// true内容是一样的s1 s2是 false说明它们不是同一个对象——一个在常量池里一个在堆里。但s1.equals(s2)是 true因为equals()比较的是字符串的内容不是引用地址。字符串常量池的四个关键特性学完之后我把字符串常量池的特性总结了四条1. 不可变性String 对象一旦创建它的值就不能改了。你做的任何修改操作比如concat()、replace()、substring()都是创建了一个新对象原来的字符串不变。我之前不理解为什么 String 要设计成不可变的。后来才知道不可变是常量池能工作的前提——如果字符串可变两个引用共享同一个 “abc”其中一个改了另一个就乱了。2. 共享性相同的字符串字面量在常量池里只存一份。不管你在代码里写了多少次hello常量池里只会有一个hello对象所有引用都指向它。这就是为什么前面那个例子可以用判断Stringxabc;Stringyabc;System.out.println(xy);// true指向同一个常量池对象3. 动态性常量池不是编译完就定死了程序跑起来之后也可以往里面加东西。最典型的例子是String.intern()方法StringsnewString(abc).intern();intern()的作用是去常量池里找有没有相同内容的字符串如果有就返回常量池里的那个引用如果没有就把当前字符串的内容放到常量池里。intern()这个方法的本质是手动把堆里的字符串注册到常量池里。4. 位置挪到了堆里JDK 7 之前常量池在永久代JDK 7 之后挪到了堆里。这样做的直接好处是堆空间可以动态扩展不用担心 PermGen 太小堆的 GC 机制更强常量池里的无用字符串可以被回收虽然概率不高但至少有了这个能力一个让我懵了好久的细节学这篇的时候有一个细节我纠结了很久new String(abc)创建的两个对象在内存里到底是什么关系我画了一个更详细的图帮自己理解栈 堆 ┌─────────┐ ┌────────────────────────────┐ │ s │ ──────→│ new String (value char[]) │ │ (引用) │ │ ┌──────────────────────┐ │ └─────────┘ │ │ char[] 引用 ────────→ │ │ │ └──────────────────────┘ │ │ │ │ 字符串常量池 │ │ ┌──────────────────────┐ │ │ │ abc → char[]对象 │ │ │ └──────────────────────┘ │ └────────────────────────────┘new 出来的 String 对象内部有一个value字段char[] 类型它引用的就是常量池里那个abc的底层 char 数组。所以整个链路是s栈引用→new String实例堆对象→ 共享的char[]数组常量池的底层数据。也就是说常量池里的abc和 new 出来的 String共享了底层的字符数据。常量池存了一份 char[]堆里的对象拿着一个引用指向它不再重复存一份内容。这个机制我之前完全不知道。了解了之后再看 “两个对象” 这个说法才真正理解了是哪两个对象。最后串一下和前面几篇的关系学到这里我发现这一篇其实是把前面三篇的知识点串起来了栈——方法里的 String 引用存在栈帧里堆——new String()的实例存在堆里方法区/元空间——类的字节码信息、class 文件常量池在这个区域字符串常量池——JDK 7 在堆里存字符串字面量一个简单的String s new String(abc)牵扯到了 JVM 三大内存区域。学完前三篇再来看这个确实有一种哦原来如此的感觉。

相关新闻

从WAIC看AI办公新趋势:会议助手正在从“记录工具”变成“组织智能体”

从WAIC看AI办公新趋势:会议助手正在从“记录工具”变成“组织智能体”

WAIC 2026 的主题是“智能伙伴,共创未来”。这一主题释放出一个清晰信号:AI办公正在从单点工具阶段,进入智能体协作阶段。对于企业、政府机关、军工单位、纪检监察、科研院所、医院和高校来说,AI会议助手不应只是录音转文字工具&a…

2026/7/2 2:58:37阅读更多 →
设备树编译后工程编译报错解决方法

设备树编译后工程编译报错解决方法

设备树编译后工程编译报错 正点原子第 7.1 节讲解编译设备树之后,再去编译工程时,可能会出现以下报错:解决办法:在设备树目录下,执行 make dtbs 之前先执行一次 make clean,即可解决。正点原子的视频和文档…

2026/7/2 2:58:37阅读更多 →
在线游戏反作弊技术:从原理到实战应用

在线游戏反作弊技术:从原理到实战应用

1. 在线多人游戏反作弊技术深度解析在竞技游戏领域,作弊行为如同附骨之疽,始终困扰着开发者和玩家。我曾参与多个大型在线游戏的防作弊系统设计,亲眼见证了这个没有硝烟的战场上攻防双方的激烈较量。作弊不仅破坏游戏平衡,更会直接…

2026/7/2 2:58:37阅读更多 →
AI工具2026:专业Figma插件与网页端UI设计测评

AI工具2026:专业Figma插件与网页端UI设计测评

说实话,做设计这行十几年了,我见过太多号称能“颠覆行业”的工具,最后大多雷声大雨点小。但2026年这波AI原型工具,确实让我感觉不一样了。它们不再是那种只能改改文案、换换图片的“伪AI”,而是真的能理解你的设计意图…

2026/7/2 6:54:00阅读更多 →
推荐 3 个 Vibe Coding 中文开源教程,从入门到实战

推荐 3 个 Vibe Coding 中文开源教程,从入门到实战

Vibe Coding 最近一年都很火,最近一个月更是强势扩散到了非程序员圈子里,普及率越来越高了! 这个词最早由 Andrej Karpathy 在 2025 年 2 月提出。我们可以把它概括为一种自然语言驱动的 AI 辅助开发方式:你描述目标,…

2026/7/2 6:54:00阅读更多 →
【限时开源】我们沉淀了6年的Gradle多模块最佳实践模板(含自动模块校验脚本、IDEA导入预设配置、跨环境Profile隔离方案),仅开放前200名领取

【限时开源】我们沉淀了6年的Gradle多模块最佳实践模板(含自动模块校验脚本、IDEA导入预设配置、跨环境Profile隔离方案),仅开放前200名领取

更多请点击: https://codechina.net 第一章:Gradle多模块构建的核心价值与演进挑战 在现代Java/Kotlin企业级项目中,Gradle多模块构建已从“可选实践”演变为支撑可维护性、可扩展性与协作效率的基础设施。其核心价值在于通过逻辑解耦实现关…

2026/7/2 6:54:00阅读更多 →
铜钟音乐:如何打造零广告的纯净听歌体验完整指南

铜钟音乐:如何打造零广告的纯净听歌体验完整指南

铜钟音乐:如何打造零广告的纯净听歌体验完整指南 【免费下载链接】tonzhon-music 铜钟「Tonzhon」: 干净纯粹的音乐平台 (铜钟已不再使用原来的 tonzhon.com,现在的 tonzhon.com 不是正版的铜钟) 项目地址: https://gitcode.com/GitHub_Trending/to/to…

2026/7/2 6:54:00阅读更多 →
npm 预发布版本管理实战:3 种 beta 发布策略与版本号规范详解

npm 预发布版本管理实战:3 种 beta 发布策略与版本号规范详解

1. 预发布不是“发着玩”,而是工程信任的临界点 很多人把 npm publish --tag beta 当成一个加个标签的快捷操作——就像给代码打个草稿标记。我试过在三个中型前端组件库项目里这么干,结果是:下游团队一边用着带 beta.3 的包,一边在 Slack 里问“这个 API 是不是还没定稿”…

2026/7/2 6:54:00阅读更多 →
深海定点监测如何选稳定单点海流计?偶信产品适配复杂海域工况吗?

深海定点监测如何选稳定单点海流计?偶信产品适配复杂海域工况吗?

在海洋科研、资源开发与生态保护的浪潮中,深海定点监测是解锁海洋奥秘的关键钥匙,而稳定可靠的单点海流计则是这一环节的核心装备。面对高压、高腐蚀、流态复杂的深海环境,如何精准挑选适配的单点海流计?以技术自主创新见长的偶信…

2026/7/2 6:48:59阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/7/1 4:42:14阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/7/1 5:19:01阅读更多 →
塞尔达传说旷野之息存档修改器:3分钟掌握海拉鲁世界自由定制技巧

塞尔达传说旷野之息存档修改器:3分钟掌握海拉鲁世界自由定制技巧

塞尔达传说旷野之息存档修改器:3分钟掌握海拉鲁世界自由定制技巧 【免费下载链接】BOTW-Save-Editor-GUI A Work in Progress Save Editor for BOTW 项目地址: https://gitcode.com/gh_mirrors/bo/BOTW-Save-Editor-GUI 想在《塞尔达传说:旷野之息…

2026/7/2 0:03:01阅读更多 →
告别 AccessKey:多云平台 CLI OAuth 免密认证完全指南

告别 AccessKey:多云平台 CLI OAuth 免密认证完全指南

在本地开发环境使用云厂商 CLI 时,传统的 AccessKey(AK)方式需要手动创建、下载和保管密钥,不仅繁琐,还存在泄漏风险。其实,主流云平台都已提供基于 OAuth 2.0 的免密认证方案,让开发者可以通过浏览器登录一次性完成授权,CLI 自动管理临时凭证的刷新,兼顾了便利与安全…

2026/7/2 0:03:01阅读更多 →
基于13DOF传感器与PIC32MZ的高精度嵌入式导航系统设计

基于13DOF传感器与PIC32MZ的高精度嵌入式导航系统设计

1. 项目背景与核心价值在嵌入式系统开发领域,高精度定位与导航一直是极具挑战性的技术方向。传统方案往往面临成本、精度和实时性难以兼顾的困境。这个项目通过13DOF(13自由度)传感器组合与PIC32MZ2048EFH100高性能MCU的协同工作,…

2026/7/2 0:03:01阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/2 0:33:58阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/2 1:32:11阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/2 1:50:13阅读更多 →