核心是定位无节制创建/持有/缓存String的对象,jmap抓Heap Dump(优先live模式)、MAT分析引用链(聚焦Leak Suspects、Histogram、Dominator Tree及Path to GC Roots),结合常见泄漏场景验证修复。

遇到大量 String 对象引发的 OOM,核心不是“删掉字符串”,而是揪出谁在无节制地创建、持有、缓存它们。jmap 负责抓现场,MAT 负责审线索,两者配合才能快速定位根因。
用 jmap 抓取有效 Heap Dump
生产环境不能等 OOM 发生才动手,但也不能随便 dump——要兼顾准确性与影响可控。
-
优先选 live 模式:执行
jmap -dump:live,format=b,file=heap.hprof <pid></pid>,只保留存活对象,文件更小、分析更快,也更贴近真实泄漏状态 -
进程卡死时再用 -F 强制模式:如
jmap -F -dump:format=b,file=heap.hprof <pid></pid>,但会跳过 GC 清理,可能混入本该回收的对象,需在 MAT 中多一步过滤 -
提前配置自动 dump 更稳妥:启动参数加上
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/dump/,OOM 一发生,快照就已落盘,避免人工干预延误 - 注意磁盘和权限:String 堆积常导致 dump 文件达数 GB,确保目标路径有足够空间;运行 jmap 的用户需对 Java 进程有读权限,对输出目录有写权限
在 MAT 中聚焦 String 相关线索
MAT 不是看谁占内存多就点谁,而是顺着引用链,找到“不该活却一直活着”的源头。
- 先看 Leak Suspects Report:打开 dump 后自动弹出,重点看 “One instance of ‘java.util.ArrayList’ dominates the heap” 这类提示——它背后往往就是 String 容器
-
直奔 Histogram 视图,筛选 java.lang.String:右键 → “Group by: Package”,或直接在 Class Name 栏输入
java.lang.String;关注 “Retained Heap” 列,排序后看前几项——哪个包下的 String 占比异常高? - 点开高 Retained Heap 的 String 实例,查 Dominator Tree:看它被谁 dominator(支配),通常会指向某个静态 Map、ThreadLocal 或单例缓存对象
-
右键 → Path to GC Roots → exclude weak/soft references:排除弱引用干扰,只看强引用链;如果路径终点是
java.lang.ThreadLocal$ThreadLocalMap或static final HashMap,基本锁定泄漏点
常见 String 泄漏场景与验证方式
不是所有 String 多都算问题,得判断是否“业务已结束,引用还挂着”。
- 日志框架中的 MDC/NDC:比如 SLF4J 的 MDC.put("traceId", ...) 后未 clear(),线程复用时 traceId 累积;检查 ThreadLocalMap 中 key 为 MDC 的 entry 数量是否随请求增长
- JSON 序列化缓存:FastJSON 或 Jackson 配置了全局缓存策略,反复解析相同结构的字符串,生成大量重复 String;在 Histogram 中观察是否出现大量内容高度相似的 String 实例
-
静态集合误用:如
public static List<string> cache = new ArrayList();</string>,接口每调用一次就 add 一个 UUID 字符串,且无清理逻辑;MAT 中可看到该 List 的 size 持续增大,且每个元素都是新 String - 数据库字段映射不当:MyBatis 将 CLOB 或长文本字段映射为 String,但业务只取前 100 字符,却把整 MB 内容全加载进内存;结合 SQL 日志 + MAT 中 String 内容预览可快速识别
确认并修复后的关键验证动作
改完代码不等于问题消失,得用数据闭环验证。
- 压测对比:用相同流量压测修复前后,观察堆内存使用曲线是否不再持续攀升,Full GC 次数是否下降
-
监控新增指标:在应用中埋点统计关键缓存容器 size、MDC entry 数量、或自定义 JVM 指标(如
string_cache_size),接入 Prometheus+Grafana 实时观测 - 保留一份修复前 dump 做基线:下次同类问题出现时,可用 MAT 的 Compare Basket 功能,快速比对 String 实例增长差异,节省 70% 分析时间

















