java中强引用无法自动释放_java中强引用、弱引用、软引用、虚引用学习

文章目录

强引用

弱引用

软引用

虚引用

将引用之前首先让我们一起回顾一下

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的时候,对象会被回收掉!!!

e6dee39265d2b0a8d8aec01648db8562.png

弱引用

引用是用来描述非必须对象的,当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());

}

d981e80bfb8c4f700e2c79c99c74d1ed.png

由控制台输可以看出,只要是弱引用,只要发生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());

}

dd7b02691f22e1f218961be02822e296.png

由上可看出由于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));

}

21e194b5fb364195052cab537db99a5a.png

虚引用

虚引用:垃圾回收时回收,无法通过引用取到对象值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());

}

13126d06f2fc5be9ea56431ea3e34bdf.png

虚引用打印的值永远为null,唯一用处就是显示enqueue(入队列)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值