JDK6中String.intern()会将字符串复制到永久代且不可回收,易引发java.lang.OutOfMemoryError: PermGen space;应禁用滥用,改用ConcurrentHashMap等可控缓存替代。

在 JDK 6 中,String.intern() 是引发永久代(PermGen)溢出的典型原因。这是因为 JDK 6 的字符串常量池位于永久代内,每次调用 intern() 都会将字符串对象**复制一份到永久代**,而永久代空间默认很小(通常几 MB),且无法被常规 GC 回收,极易填满。
确认是否为常量池导致的 PermGen 溢出
观察 OOM 异常信息是否包含:
java.lang.OutOfMemoryError: PermGen space
并且堆栈中出现 String.intern(Native Method) 或类似调用链。这是最直接的信号。
临时缓解:扩大永久代空间(仅限应急)
通过 JVM 参数临时放宽限制(不解决根本问题,但可争取排查时间):
- -XX:PermSize=64m:设置永久代初始大小
- -XX:MaxPermSize=256m:设置永久代最大上限(建议不超过 512m,避免影响 GC 效率)
⚠️ 注意:这只是“扩容止痛”,不能替代代码修复;过大的 PermSize 可能掩盖真实泄漏,且在 JDK 7+ 已废弃,不具备长期兼容性。
根本修复:避免滥用 String.intern()
绝大多数业务场景下,intern() 并非必需。以下为安全替代方案:
- 字符串比较优先使用
.equals(),而非依赖引用相等(==) - 若需去重缓存,改用
ConcurrentHashMap<String, String>自管理,可控、可清理、支持弱引用 - 确需 intern 的场景(如极高频枚举字符串匹配),应严格限制输入范围,例如只对预定义白名单字符串调用
- 禁止在循环或日志拼接、SQL 构建等动态生成字符串路径中无条件调用
intern()
验证与监控建议
上线前可通过 JMX 或 jstat -gcpermcapacity <pid> 观察永久代使用趋势;也可添加 JVM 参数:
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps
重点关注 Full GC 是否频繁触发且 PermGen 使用率持续攀升。

















