文章目录
强引用
弱引用
软引用
虚引用
将引用之前首先让我们一起回顾一下
java对象的生命周期
强引用
在实际开发场景中,我们一般使用的都是强引用,只要强引用存在,垃圾回收即使OOM也不会回收,知道强引用释放以后,对象才会被释放掉,可以显示地将引用赋值为null,这样的话,JVM会在合适的时间回收该对象。
以下是测试:
public void method() {
Object o = new Object();
Object[] os = new Object[800000];
System.out.println(os.length);
}
@Test
public void srongReference(){
method();
}
在method方法没有结束之前,method中定义的局部变量的对象是不会被回收,method结束后会在适合GC。
回收测试:
@Test
public void strongReference() throws InterruptedException {
Thread.sleep(40 * 1000);
System.out.println("加载");
method();
Object o = new Object();
Object[] os = new Object[800000];
System.out.println("判断是否回收");
Thread.sleep(20 * 1000);
o = null;
os = null;
System.gc();
System.out.println("强制回收");
Thread.sleep(100 * 1000);
}
通过 jconsole监控内存变化,发现当强引用关系解除以后,强制GC的时候,对象会被回收掉!!!
弱引用
引用是用来描述非必须对象的,当JVM进行垃圾回收时候,无论内存是否充足,都会回收。
@Test
public void weakReference() {
// ArrayListps = new ArrayList<>();//list存储的对象引用也是强引用关系
// ps.add(person);
WeakReference wf = new WeakReference<>(new Person("weijie", 25));
System.out.println(wf.get());
System.out.println(wf.isEnqueued());
System.gc();
System.out.println(wf.get());
System.out.println(wf.isEnqueued());
}
由控制台输可以看出,只要是弱引用,只要发生GC对象会被回收。
@Test
public void weakReference() {
Person person = new Person("weijie", 25);
ArrayList ps = new ArrayList<>();//list存储的对象引用也是强引用关系
ps.add(person);
WeakReference wf = new WeakReference<>(person);
System.out.println(wf.get());
System.out.println(wf.isEnqueued());
System.gc();
System.out.println(wf.get());
System.out.println(wf.isEnqueued());
}
由上可看出由于list导致对象存在强引用关系,此时加上弱引用的话对象也不会被回收,需要手动将person=null 接触强引用关系以后,对象才会GC时候回收
软引用
用来描述一些有用但并不是必须的对象,对于软引用关联的对象,只有在内存不足的时候JVM才会回收该对象,这一点可以很好解决OOM问题,这个特性很适合用来实现缓存:网页缓存、图片缓存等。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列中。
@Test
public void softReference() {
SoftReferenceCache referenceCache = new SoftReferenceCache<>();
referenceCache.put(0, new Person("weijie", 24));
System.gc();
System.out.println(referenceCache.get(0));
}
虚引用
虚引用:垃圾回收时回收,无法通过引用取到对象值PhantomReference 唯一的用处就是跟踪 referent 何时被 enqueue(入队列) 到 ReferenceQueue 中虚引用主要用来跟踪对象被垃圾回收的活动。
虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用, 来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列, 那么就可以在所引用的对象的内存被回收之前采取必要的行动。
@Test
public void phantomReference(){
Person person = new Person("weijie", 24);
ReferenceQueue referenceQueue = new ReferenceQueue();
PhantomReference personPhantomReference = new PhantomReference(person, referenceQueue);
System.out.println(referenceQueue.poll());
System.out.println(personPhantomReference.get());
//判断对象是否被标记回收
System.out.println(personPhantomReference.enqueue());
person = null;
System.out.println(personPhantomReference.get());
System.out.println(personPhantomReference.enqueue());
}
虚引用打印的值永远为null,唯一用处就是显示enqueue(入队列)