String不可变性堵住四大安全缺口:防止敏感参数(如密码、URL)被中间环节篡改;保障类加载与SecurityManager检查的标识符可信;避免跨模块传递时的上下文污染;消除常量池共享导致的静默修改风险。

面试时谈到 String 不可变性的安全性优势,重点不是罗列“安全”二字,而是讲清它在哪些具体场景中堵住了真实风险缺口。
防止敏感数据被中间环节篡改
String 大量用于承载关键路径信息:数据库连接 URL、HTTP 请求头、文件路径、用户凭证(如密码原文)、API 签名原文等。这些值一旦被修改,可能直接触发越权、路径遍历或 SQL 注入。
不可变性切断了“拿到引用就能改内容”的信任链。例如:
- 一个校验方法接收 password 字符串做比对,调用方传入后,无论该方法内部、还是被其他过滤器/日志组件拦截,都无法偷偷把
password.toUpperCase()后覆盖原始值——它只会生成新对象,原 password 始终不变; - 若 String 可变,恶意线程在 JDBC 连接建立前瞬间修改
"jdbc:mysql://127.0.0.1:3306/admin"为"jdbc:mysql://attacker.com:3306/admin",后果严重。
保障类加载与安全检查机制可信
JVM 依赖 String 精确表示类名、包名、资源路径等元数据。类加载器靠全限定类名定位 .class 文件,安全管理器(如 SecurityManager.checkPackageAccess("java.lang"))也靠字符串匹配权限策略。
立即学习“Java免费学习笔记(深入)”;
如果 "java.lang.System" 这个字符串在类加载中途被运行时篡改,攻击者就可能绕过双亲委派,加载伪造的系统类,突破沙箱限制。String 的不可变性确保了这些标识符从字节码解析开始就恒定唯一,是 Java 安全模型的底层锚点。
避免跨模块参数污染与共享歧义
在 Web 容器、RPC 框架或权限链路中,字符串常作为上下文参数传递(如用户 ID、租户标识、traceId)。不可变性保证其在调用链中逐层流转时,不会被上游或下游模块无意覆盖。
比如 Spring Security 中 Authentication.getName() 返回的 username,或 Dubbo Attachment 中透传的 tenant-id,所有中间件(鉴权过滤器、日志埋点、监控探针)执行 replace() 或 substring() 都只产生副本,原始上下文始终受控,杜绝因“静默修改”导致的权限错乱或追踪断裂。
消除字符串常量池引发的安全副作用
常量池中多个变量可能共享同一实例(String a = "admin"; String b = "admin"; a == b 为 true)。若 String 可变,一个模块调用 a.toUpperCase() 就会意外改变 b 所见内容——这不仅破坏语义,更可能让权限校验读到被篡改的租户名或角色标识。
不可变性使共享变为安全复用:既节省内存,又彻底隔离副作用。这也是为什么注解属性(如 @RequestMapping("/user"))和 switch 字符串能被编译器和 JVM 无条件信任。


















