强软弱虚,是 Java 中比较主流的四种引用。(多念念,就顺口了)
从这四种引用的作用来看(接下来你会看到),引用,与对象的存活密不可分。也许正是因为有了 JVM 的垃圾收集器,才有了这四种引用。
我觉得直接看四种引用的概念比较好:
- 强引用;无论何时,只要有强引用关系的对象,都不会被垃圾回收器回收掉,如果内存不足的时候,直接报错
- 软引用:有软引用关系的对象,当内存即将不足的时候,会被垃圾回收器清理掉;
- 弱引用:有弱引用关系的对象,只能活到下一次垃圾回收的时候,也就是,只要发生了一次垃圾回收,那么弱引用关系的对象就被清理掉了
- 虚引用:最弱的引用,我们甚至无法通过虚引用获得关系对象的信息。它的唯一作用,就是在垃圾回收的时候,能够将相关信息放在一个队列中。进而我们可以用这个队列获得相关信息。
接下来,我们来分别看看这四种引用。
强引用
我们平时使用的都是强引用,就比如
Object o = new Object()
所以,故不多介绍。
软引用
软引用,需要用到 SoftReference 类,这个类的构造方法中放入需要进行软引用的对象。
package ref;
import java.lang.ref.SoftReference;
public class SoftRefTest {
public static void main(String[] args) {
SoftReference<String> softReference = new SoftReference<>(new String("Hello World"));
System.out.println(softReference.get());
System.gc();
// 根据 老年代 大小进行设置,占满内存
byte[] bigSize = new byte[1024 * 7168 - 354 * 1024];
System.out.println(softReference.get());
}
}
设置参数
-Xms10m -Xmx10m -XX:+PrintGCDetails
可以看到,当我们去占满内存的时候,软引用对象直接被清理掉了。最后获取其引用对象为 null。
弱引用
package ref;
import java.lang.ref.WeakReference;
public class WeakRefTest {
public static void main(String[] args) {
WeakReference<String> weakReference = new WeakReference<>(new String("Hello World"));
System.out.println(weakReference.get());
System.gc();
System.out.println(weakReference.get());
}
}
最后的输出为:
Hello World
null
虚引用
虚引用的使用,与前面有所差距。
/**
* Creates a new phantom reference that refers to the given object and
* is registered with the given queue.
*
* <p> It is possible to create a phantom reference with a <tt>null</tt>
* queue, but such a reference is completely useless: Its <tt>get</tt>
* method will always return null and, since it does not have a queue, it
* will never be enqueued.
*
* @param referent the object the new phantom reference will refer to
* @param q the queue with which the reference is to be registered,
* or <tt>null</tt> if registration is not required
*/
public PhantomReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}
这是虚引用的构造器,它需要两个参数,一个是对象,另一个对引用队列。
package ref;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class PhantomRefTest {
public static void main(String[] args) throws InterruptedException {
ReferenceQueue<String> refQueu = new ReferenceQueue<>();
PhantomReference<String> refPhantom = new PhantomReference<>(new String("Hello World"), refQueu);
System.out.println(refPhantom.get());
System.gc();
System.out.println(refQueu.remove());
}
}
最后输出为:
null
java.lang.ref.PhantomReference@61bbe9ba