想象Java对象就像社会中的不同人群,有的备受重视(强引用),有的可有可无(软引用),有的随叫随走(弱引用),还有的如同幽灵(虚引用)。今天我们就用最生动的比喻,带你彻底搞懂这四种引用类型!
引用类型 | 生存法则 | 回收时机 | 典型应用场景 |
---|---|---|---|
强引用 | 宁死不屈 | 永不回收 | 日常对象创建 |
软引用 | 内存不足才投降 ️ | 内存不足时 | 缓存实现 |
弱引用 | 见GC就投降 | 下次GC时 | WeakHashMap |
虚引用 | 幽灵观察者 | 随时可能回收 | 对象回收跟踪 |
Object strongRef = new Object(); // 经典强引用
strongRef = null; // 解除引用,对象可被回收
SoftReference<byte[]> softRef =
new SoftReference<>(new byte[1024*1024]); // 1MB缓存
byte[] cache = softRef.get(); // 获取引用
// 图片缓存示例
Map<String, SoftReference<Bitmap>> imageCache = new HashMap<>();
void loadImage(String url) {
Bitmap image = download(url);
imageCache.put(url, new SoftReference<>(image));
}
WeakReference<Object> weakRef =
new WeakReference<>(new Object());
// WeakHashMap实现原理
WeakHashMap<Key, Value> weakMap = new WeakHashMap<>();
ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef =
new PhantomReference<>(new Object(), queue);
// 监控对象回收
new Thread(() -> {
while(true) {
Reference<?> ref = queue.remove();
System.out.println("对象被回收了!");
}
}).start();
// 直接内存回收监控(如ByteBuffer)
public class Cleaner extends PhantomReference<Object> {
private final Runnable cleanupTask;
// 实现清理逻辑...
}
// 测试代码框架
void testReference(ReferenceType type) {
Object obj = createLargeObject();
Reference<Object> ref = createReference(type, obj);
obj = null; // 解除强引用
System.gc(); // 触发GC
checkIfCollected(ref);
}
引用类型 | 第一次GC | 内存不足时 | 强制GC |
---|---|---|---|
强引用 | 存活 | 存活 | 存活 |
软引用 | 存活 | 回收 | 存活 |
弱引用 | 回收 | 回收 | 回收 |
虚引用 | 回收 | 回收 | 回收 |
ReferenceQueue<FileChannel> queue = new ReferenceQueue<>();
WeakReference<FileChannel> ref =
new WeakReference<>(channel, queue);
// 监控线程
new Thread(() -> {
while(true) {
Reference<?> ref = queue.remove();
cleanupResources(ref);
}
}).start();
现在你已掌握:
思考题:为什么ThreadLocal使用弱引用?评论区等你高见!
#Java #JVM #内存管理 #强引用 #弱引用 #性能优化