在Java内存管理中,引用类型直接决定了对象的生命周期。除了最常见的强引用,Java还提供了软引用(SoftReference)、弱引用(WeakReference)和虚引用(PhantomReference)三种特殊引用类型。本文将结合代码示例,深入解析这四种引用的特性和使用场景。
一、强引用(Strong Reference)
1.1 基本概念
强引用是最常见的引用类型,通过new
关键字创建的对象默认都是强引用。只要强引用存在,垃圾回收器就永远不会回收被引用的对象。
// 创建强引用
Object strongRef = new Object();
// 解除强引用
strongRef = null; // 对象变为可回收状态
1.2 示例分析
public class StrongReferenceDemo {
public static void main(String[] args) {
// 创建强引用对象(占用5MB内存)
byte[] data = new byte[5 * 1024 * 1024];
// 尝试触发垃圾回收
System.gc();
// 验证对象是否被回收
System.out.println("GC后强引用对象仍然存在:" + data);
}
}
输出结果:
GC后强引用对象仍然存在:[B@1b6d3586
1.3 注意事项
- 内存泄漏常见原因:未及时解除无用对象的强引用
- 集合类中的对象需要主动移除或清空
二、软引用(SoftReference)
2.1 基本概念
软引用对象在内存充足时保留,在内存不足时会被回收。适用于实现内存敏感的缓存。
// 创建软引用
SoftReference<Object> softRef = new SoftReference<>(new Object());
// 获取对象
Object obj = softRef.get(); // 可能返回null
2.2 示例演示
public class SoftReferenceDemo {
public static void main(String[] args) {
// 创建软引用对象(占用10MB内存)
SoftReference<byte[]> softRef = new SoftReference<>(new byte[10 * 1024 * 1024]);
System.out.println("GC前:" + softRef.get());
// 尝试触发垃圾回收
System.gc();
// 分配15MB内存,触发内存不足
try {
byte[] newData = new byte[15 * 1024 * 1024];
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
System.out.println("内存不足时GC后:" + softRef.get());
}
}
运行参数:-Xmx20m -Xms20m
输出可能:
GC前:[B@1b6d3586
内存不足时GC后:null
2.3 典型应用
- 图片缓存实现
- 计算结果缓存
三、弱引用(WeakReference)与ThreadLocal
3.1 基本概念
弱引用对象只能存活到下次GC发生前,无论内存是否充足都会被回收。常用于防止内存泄漏的场景。
// 创建弱引用示例
WeakReference<Object> weakRef = new WeakReference<>(new Object());
// 立即触发GC测试
System.gc();
System.out.println(weakRef