ThreadLocal没remove内存慢慢涨最后OOM了

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