强引用
只要某个对象有强引用与之关联,JVM必定不会回收这个对象,即使在内存不足的情况下,JVM宁愿抛出OutOfMemory错误也不会回收这种对象
使用场景
Object obj = new Object();
如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象
软引用
软引用是用来描述一些有用但并不是必需的对象,只有在内存不足的时候JVM才会回收该对象
使用场景
SoftReference<String> sr = new SoftReference<String>(new String("hello"));
System.out.println(sr.get());
- 解决OOM的问题
- 实现缓存
SoftReference
除了 SoftReference(T referent)
构造方法外,还有一个SoftReference(T referent, ReferenceQueue<? super T> q)
,软引用和一个引用队列(ReferenceQueue)
联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中,作为一个Java对象,SoftReference对象除了具有保存软引用的特殊性之外,也具有Java对象的一般性
private void test() {
// 制造OOM
ArrayList<Byte[]> list = new ArrayList<>();
// 引用队列
ReferenceQueue<Byte[]> referenceQueue = new ReferenceQueue<>();
SoftReference<Byte[]> softReference = new SoftReference<>(new Byte[100000], referenceQueue);
// 软引用对象
System.out.println(softReference);
while (true) {
list.add(new Byte[100000]);
if (softReference.get() == null) {
System.out.println("软引用被回收");
SoftReference reference = (SoftReference) referenceQueue.poll();
System.out.println(reference);
}
}
}
输出结果为:
java.lang.ref.SoftReference@61bbe9ba
软引用被回收
java.lang.ref.SoftReference@61bbe9ba
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
当这个SoftReference
所软引用的Object
被垃圾收集器回收的同时,ref所强引用的SoftReference
对象被列入ReferenceQueue
。也就是说,ReferenceQueue
中保存的对象是Reference对象
,而且是已经失去了它所软引用的对象的Reference对象
。利用这个方法,我们可以检查哪个SoftReference
所软引用的对象已经被回收,同时也可以把这些失去所软引用的对象的SoftReference对象
清除掉
弱引用
弱引用和软引用不同,每次GC时,JVM都会回收这一部分对象,弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。
使用场景
- WeakHashMap
- ThreadLocal
弱引用和软引用类似,同样可以和一个引用队列(ReferenceQueue)
联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
private void test() {
// 用于触发GC
ArrayList<Byte[]> list = new ArrayList<>();
// 引用队列
ReferenceQueue<Byte[]> referenceQueue = new ReferenceQueue<>();
WeakReference<Byte[]> weakReference = new WeakReference<>(new Byte[100000], referenceQueue);
// 弱引用对象
System.out.println(weakReference);
while (true) {
list.add(new Byte[100000]);
if (weakReference.get() == null) {
System.out.println("弱引用被回收");
WeakReference reference = (WeakReference) referenceQueue.poll();
System.out.println(reference);
break;
}
}
}
输出结果:
java.lang.ref.WeakReference@61bbe9ba
弱引用被回收
java.lang.ref.WeakReference@61bbe9ba
虚引用
虚引用(PhantomReference)
顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
使用场景
虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)
联合使用(只有一个构造方法:PhantomReference(T referent, ReferenceQueue<? super T> q)
),虚引用的get方法始终返回null。
当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。