文章目录
Java 中的四种引用方式
1、强引用(Strong Reference)
- 强引用是最普遍的引用
- 当一个对象是强引用,垃圾回收器绝不会回收他
- 当内存不足时,JVM 宁愿抛出 OutOfMemoryError 错误,也不会回收具有强引用的对象,来解决内存不足问题
Object strongReference = new Object();
- 如果强引用对象不使用时,需要 弱化从而使 GC 能够回收
(1)弱化方式1
-
显示的设置 strongReference 对象为null,则 gc 认为该对象不存在引用,这时就可以回收这个对象
-
如果 strongReference 是 全局变量,就需要在不用这个对象时赋值为
null
,因为强引用不会被垃圾回收。
strongReference = null;
应用场景:在ArrayList
集合类中定义elementData
数组,在调用clear()
方法清空集合元素时,将每个数组元素被赋值为null
。目的是为了将内存数组中存放的引用类型进行内存释放,可以及时释放内存。不选择将elementData=null
,是为了避免在后续调用add()
等方法添加新元素时,需要进行内存的重新分配
//ArrayList 源码
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
(2)弱化方式2
让对象超出作用域范围,即缩小强引用的作用范围
public void test() {
Object strongReference = new Object();
// 省略其他操作
}
应用场景:在一个方法的内部有一个强引用,这个引用保存在VM Stack
栈中(GC Root*),而真正的引用对象(
Object)保存在堆中。当这个方法运行完成后,就会退出方法栈,则这个对象会被回收。
2、软引用(Soft Reference)
- 如果一个对象只具有软引用,则 内存空间充足 时,垃圾回收器就不会回收它
- 如果 内存空间不足时 ,就会回收这些对象,从而释放内存
- 软引用可以用来实现内存敏感的高速缓存
使用 SoftReference 创建软引用
// 定义和访问软引用
// 强引用
String strongReference = new String("abc");
// 软引用
String str = new String("abc");
SoftReference<String> softReference = new SoftReference<String>(str);
// 访问软引用
softReference.get();
- 软引用对象是在
jvm
内存不够的时候才会被回收,我们调用System.gc()
方法只是起通知作用,最终何时回收,由JVM
决定。 - 所以,当内存不足时,
JVM
首先将软引用中的对象引用置为null
,然后通知垃圾回收器进行回收:
//回收软引用
// 软引用
String str = new String("abc");
SoftReference<String> softReference = new SoftReference<>(str);
str = null;
// Notify GC
System.gc();
try {
byte[] buff1 = new byte[900000000]; // 内存充沛
// byte[] buff2 = new byte[900000000]; // 内存不足
} catch (Error e) {
e.printStackTrace();
}
System.out.println(softReference.get()); // abc 或 null
**应用场景:**短视频APP中的视频缓存,后退时,显示的短视频内容是重新进行请求还是从缓存中取出呢?
- 如果一个短视频在播放结束时,就进行内容的回收,则后退查看前面播放的短视频时,需要重新请求。
- 如果将播放过的短视频存储到内存中,会造成内存的开销,甚至会造成内存溢出。
此时,可以使用软引用解决这个实际问题:
//软引用案例
// 获取视频播放器对象
Player videoAlayer = new Player();
// 加载短视频
Video video = audioAlayer.getVideo();
// 将播放完毕的短视频设置为软引用
SoftReference softReference = new SoftReference(video);
// 回退或者再次播放时
if(softReference.get() != null) {
// 内存充足,还没有被回收器回收,直接获取缓存
video = softReference.get();
} else {
// 内存不足,软引用的对象已经回收
video = audioAlayer.getVideo();
// 重新构建软引用
softReference = new SoftReference(video);
}
3、弱引用(Weak Reference)
- 只具有 弱引用 的对象拥有 更短暂 的 生命周期
- 在垃圾回收器扫描的时候,不管内存是否足够,都会回收它的内存
创建弱引用,使用 WeakReference
String str = new String("abc");
WeakReference<String> weakReference = new WeakReference<>(str);
str = null;
System.gc();
// 一旦发生GC,弱引用一定会被回收
System.out.println(weakReference.get());
4、虚引用(Phantom Reference)
- 虚引用是最弱的一种引用关系
- 如果一个对象仅持有虚引用,完全不会对其生存时间构成影响,它就和没有任何引用一样,随时可能会被回收
- 主要用来跟踪对象被垃圾回收的活动,可以在垃圾收集时收到一个系统通知
public class PhantomReference<T> extends Reference<T> {
public T get() {
return null;
}
}