jvm - 强引用、软引用、弱引用(涉及WeakHashMap)、虚引用(涉及ReferenceQueue)垃圾回收时机


引用的架构图:

Reference在java.lang.ref包下

 

1、强引用(默认)

将对象赋值给以引用变量,这个引用变量就是一个强引用,这个强引用指向的对象即使出现了OOM也不会被回收。

代码举例:
obj2也是强引用,所以即使obj不再指向new Object()对象了,但是该对象依旧不会被GC

2、软引用

SoftReference softReference = new SoftReference<>(new Object());

适用于对内存敏感的程序中,如高速缓存:

即软引用只会因内存不够用引起的gc时被回收(前提是强引用不存在),而不是一旦gc就会被回收。

 

代码举例:
内存够用的时候:(软引用不会被回收)

注意,该软引用的对象仍然不会被GC,因为没有OOM!即使其内封装的o1引进置为空了,也不会影响

 

结果:

内存不够用的时候:(软引用会被回收)
不需要手动System.gc(),因为内存不够用了,会自动gc;
需要在IDEA中配置JVM参数,见方法的注释。

结果:
(最后一行显示,该软引用被gc了)
另外OOM也会报错,只是这里没有截出来

 

小总结:软引用会被垃圾回收的场景:强引用置为空了,且因为OOM而引起GC时,即
OOM,引起的gc不会使软引用被回收;
强引用置为空了,调用System.gc();不会引起软引用的回收;

 

3、弱引用(比软引用的生存期更短)

WeakReference weakReference = new WeakReference<>(new Object());

但也只有被认定为垃圾后,才会回收(所以需要o1 = null这行代码)

代码举例:

结果:(即使在内存充足的情况下,只要发生GC,弱引用就会被回收)

软引用、弱引用的适用场景:
键:String:图片路径
值:SoftReference<Bitmap>:相应图片对象关联的软(弱)引用
使用imageCache作为缓存,每加载了一张图片,就存进这个imageCache里(本质是HashMap.put())

详细代码:(Image换成正确的)

 

小总结:弱引用会被垃圾回收的场景:强引用置为空了,一旦GC(即不要求是OOM引起的gc),即
gc不会使软引用被回收;(还必须要强引用置为空)

 

既然你知道弱引用,那么你还知道WeakHashMap吗?

HashMap和WeakHashMap一样地位,都是继承AbstractMap抽象类,实现Map接口

 

直接上代码,比较HashMap和WeakHashMap的区别

结果:(WeakHashMap是一种弱引用map,内部的key会自动存储为弱引用,当jvm gc的时候,如果这些key没有强引用存在的话,会被gc回收掉,下一次当我们操作map的时候会把对应的Entry整个删除掉,基于这种特性,WeakHashMap特别适用于缓存处理。)

即缓存处理,可以
1、将软引用(发生了OOM才会被清除)作为普通hashMap的值放入;(若想删除某个图片,只需将image置为null,当下次发生OOM时,该普通hashMap中的该键值图片会被自动删除)
2、也可以将普通(未被封装成软引用)的图片对象作为WeakHashMap的值放入。(若想删除某个图片,只需将该image对应的键(即key)设为null,当下次gc时,会被删掉)

 

会被回收情况的小总结:

1、软引用
强引用为空 +
OOM引发的gc .

2、弱引用
强引用为空 +
gc(不要求是OOM引发的) .

 

4、虚引用

它不会影响对象的生命周期!!!!这是它存在的最大意义!!!!
虚引用PhantomReference不能单独使用也不能通过它访问对象(即phantomReference.get()结果为null),虚拟引用必须和引用队列(ReferenceQueue)联合使用。(创建引用的时候,还可以添加第二个参数来指定关联的referenceQueue引用队列,当ga释放对象内存时,会将被释放的引用加入到引用队列中)相当于一种 通知机制了,即出现在引用队列中的引用意味着被回收了。
虚引用和引用队列的结合,完完全全是为了实现通知机制。
finalize()方法由GC调用。
 
先讲一下ReferenceQueue:
引用的构造方法可以(至少软引用、弱引用、虚引用可以, 强引用怎么搞没验证)填上第二个参数:引用队列。
 
 
代码举例:
(此处之所以用WeakReference而不用PhantomReference的原因是因为PhantomReference的不能通过它访问对象的特点,而不方便作为代码展示,所以用的是WeakReference(事实上,软、弱引用都可以)来和ReferenceQueue结合)
(事实上,软、弱引用都可以和ReferenceQueue结合,这些引用达到GC条件时,都会把对象先放进ReferenceQueue中,再清除自己本身,见结果最后一行(非null))
注意一下WeakReference的构造方法,两个参数!多了一个ReferenceQueue
 
运行结果:
在gc之前,会被放到ReferenceQueue中(即如ReferenceQueue中所说,被回收前需要被放到引用队列中保存一下)
 
 
下面倒回来再讲虚引用:
虚引用和引用队列的结合,完完全全是为了实现通知机制。
结果:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值