1. ThreadLocal内存泄漏深度解析
在Java开发中,ThreadLocal是一个常用的线程局部变量工具类,但不当使用会导致内存泄漏问题。本文将深入分析ThreadLocal的内存泄漏机制,从Java引用类型到ThreadLocal源码实现,最后给出实际开发中的解决方案。
1.1 Java引用类型体系
Java从1.2版本开始引入了java.lang.ref包,提供了四种引用类型,用于更精细地控制对象生命周期:
1.1.1 强引用(Strong Reference)
最常见的引用类型,通过new关键字创建的对象默认都是强引用。只要强引用存在,垃圾回收器就永远不会回收被引用的对象。
java复制Object obj = new Object(); // 强引用
强引用对象只有在显式设置为null时,才会被垃圾回收器考虑回收。如果内存不足,JVM会抛出OutOfMemoryError而不是尝试回收强引用对象。
1.1.2 软引用(SoftReference)
软引用对象在内存不足时会被回收。适合用于实现内存敏感的缓存。
java复制SoftReference<byte[]> softRef = new SoftReference<>(new byte[1024*1024]);
软引用特点:
- 当内存充足时,不会被回收
- 当内存不足时,会被回收
- 适合缓存图片等大对象
1.1.3 弱引用(WeakReference)
弱引用对象在下一次垃圾回收时就会被回收,不管内存是否充足。
java复制WeakReference<Object> weakRef = new WeakReference<>(new Object());
弱引用特点:
- 只要发生GC就会被回收
- 常用于防止内存泄漏
- ThreadLocal中的Entry就使用了弱引用
1.1.4 虚引用(PhantomReference)
虚引用主要用于跟踪对象被垃圾回收的状态,必须与ReferenceQueue配合使用。
java复制ReferenceQueue queue = new ReferenceQueue();
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue);
虚引用特点:
- 无法通过虚引用获取对象
- 主要用于对象回收跟踪
- 需要配合ReferenceQueue使用
1.2 ThreadLocal实现原理
ThreadLocal的核心设计思想是为每个线程维护一个独立的变量副本,实现线程隔离。
1.2.1 ThreadLocal基本使用
java复制public class UserContext {
private static final ThreadLocal<User> currentUser = new ThreadLocal<>();
public static void set(User user) {
currentUser.set(user);
}
