线上服务跑了三天,突然 OOM 挂了。重启,三天后又挂了。
内存 dump 拉下来,用 MAT 一看——堆里有几十万个UserContext对象,全被 ThreadLocal 引着,GC 收不掉。
排查
代码里有个全局的用户信息持有者:
publicclassUserContext{privatestaticfinalThreadLocal<User>CURRENT_USER=newThreadLocal<>();publicstaticvoidset(Useruser){CURRENT_USER.set(user);}publicstaticUserget(){returnCURRENT_USER.get();}}每个请求进来,Filter 把用户信息塞进去:
UserContext.set(currentUser);chain.doFilter(request,response);问题在哪?Filter 的doFilter执行完后——没调remove()。
线程回到线程池,ThreadLocal 里的 User 对象还挂着。下一个请求如果是另一个用户,ThreadLocal 被set覆盖,旧 User 对象失去了强引用——但 ThreadLocal 内部的 Entry 还在,弱引用的 key 被 GC 了,value 却因为线程没死而一直存在。
这就是 ThreadLocal 内存泄漏的标准剧本。
根因:ThreadLocal 的内存模型
ThreadLocal 不存数据——数据存在 Thread 对象里的ThreadLocalMap。每个 Thread 有一个 Map,key 是 ThreadLocal 的弱引用,value 是你塞进去的对象。
Thread → ThreadLocalMap → Entry[弱引用→ThreadLocal, 强引用→User]线程跑完回到线程池,线程没死 → ThreadLocalMap 没清 → Entry 还在。GC 回收了 ThreadLocal 对象本身(因为是弱引用),但value(User)是强引用,不收。
这个 value 就永远挂在 Thread 的 ThreadLocalMap 里,直到线程销毁。
正确写法:finally 里 remove
try{UserContext.set(currentUser);chain.doFilter(request,response);}finally{UserContext.remove();// ✅ 必须清}remove()会删除 ThreadLocalMap 里对应的 Entry,value 失去引用,可以被 GC 回收。
任何地方用了ThreadLocal.set(),必须在 finally 里调remove()。没有例外。
ThreadLocal 另外两个坑
坑一:线程池复用,读到上一个任务的脏数据
ThreadLocal<String>traceId=newThreadLocal<>();// 任务1traceId.set("req-001");// 忘记 remove// 任务2(同一个线程)Stringid=traceId.get();// → "req-001",脏数据日志里两个不同请求的 traceId 一样——排查链路全乱。
坑二:父子线程传递用 InheritableThreadLocal,线程池不生效
InheritableThreadLocal<String>tl=newInheritableThreadLocal<>();tl.set("parent-value");newThread(()->{System.out.println(tl.get());// ✅ "parent-value"}).start();InheritableThreadLocal在创建子线程时会把父线程的值拷过去。但线程池里线程是复用的,只在第一次创建时拷贝一次,后面不会更新。
线程池场景用阿里的TransmittableThreadLocal:
TransmittableThreadLocal<String>tl=newTransmittableThreadLocal<>();tl.set("value");executor.execute(TtlRunnable.get(()->{System.out.println(tl.get());// ✅ 每次都能拿到最新值}));ThreadLocal 三个原则:
- 用了
set就必须在 finally 里remove - 线程池场景更要
remove——线程不销毁,泄漏累积 - 父子线程传递用
TransmittableThreadLocal,别用InheritableThreadLocal
四行代码的事,忘了就是 OOM。
关于作者:无羡,独立开发者,全栈工程师,专注 AI 应用与微服务架构。
📌 分类:技术复盘
🔗 个人博客 — 更多技术文章
✨ 开发者福利整理 — 云服务资源汇总
📂 软件工坊 — 我的技术分享
🌐 个人门户 — 独立开发作品全集