谈谈Java对象的强引用,软引用,弱引用,虚引用分别是什么
整体结构
java提供了4中引用类型,在垃圾回收的时候,都有自己的各自特点。

为什么要区分这么多引用呢,其实这和Java的GC有密切关系。
强引用(默认支持模式)
- 把一个对象赋给一个引用变量,这个引用变量就是一个强引用。
- 强引用是我们最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还活着
- 当内存不足的时候,jvm开始垃圾回收,对于强引用的对象,就算出现OOM也不会回收该对象的。
因此,强引用是造成java内存泄露的主要原因之一。 - 对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显示的将引用赋值为null,GC就会回收这个对象了。
案例
public static void main(String[] args) {
Object obj=new Object();//这样定义就是一个强引用
Object obj2=obj;//也是一个强引用
obj=null;
System.gc();
//不会被垃圾回收
System.out.println(obj2);
}
软引用(SoftReference)
- 软引用是一种相对强化引用弱化了一些引用,需要使用java.lang.SoftReference类来实现。
- 对于只有软引用的对象来说,
当系统内存充足时,不会被回收;
当系统内存不足时,会被回收; - 软引用适合用于缓存,当内存不足的时候把它删除掉,使用的时候再加载进来
案例
/**
* jvm配置配置小的内存,故意产生大的对象,导致OOM,
* 验证软引用在内存足够的前后是否被回收。
* 参数:-Xms:5M -Xmx:5M
* @param args
*/
public static void main(String[] args) {
Object obj=new Object();//这样定义就是一个强引用
//软引用需要使用java.lang.SoftReference来实现
//现在sf就是一个软引用
SoftReference sf=new SoftReference(obj);
obj=null;
System.out.println("内存足够软引用引用的对象"+sf.get());
try {
final byte[] bytes = new byte[8 * 1024 * 1024];
} catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println("内存不够:软引用引用的对象:"+sf.get());
}
}
结果:

弱引用
- 弱引用需要用java.lang.WeakReference类来实现,它比软引用的生存期更短。
* 如果一个对象只是被弱引用引用者,那么只要发生GC,不管内存空间是否足够,都会回收该对象。
- 弱引用适合解决某些地方的内存泄漏的问题
- ThreadLocal静态内部类ThreadLocalMap中的Entiry中的key就是一个虚引用;
案例
public static void main(String[] args) {
Object obj=new Object();
WeakReference wrf=new WeakReference(obj);
obj=null;
System.out.println("未发生GC之前"+wrf.get());
System.gc();
System.out.println("内存充足,发生GC之后"+wrf.get());
}
结果:
未发生GC之前java.lang.Object@2d363fb3
内存充足,发生GC之后null
ThreadLocal

你知道弱引用的话,能谈谈WeakHashMap吗?
WeakHashMap的键是“弱键”,也就是键的引用是一个弱引用。
public static void main(String[] args) {
WeakHashMap<String,Integer> map=new WeakHashMap<>();
String key = new String("wekHashMap");
map.put(key,1);
key=null;
System.gc();
System.out.println(map);
}
结果:map为空了。
理论上我们只是把引用变量key变成null了,"wekHashMap"字符串应该被Map中key引用啊,不应该被GC回收啊,
但是因为key是弱引用,GC回收的时候就忽略了这个引用,把对象当成垃圾收回了。
虚引用
- 虚引用需要 java. langref.PhantomReference类来实现。
- 顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。
如果一个对象仅被虛引用持有,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。 - 它不能单独使用也不能通过它访问对象,虚引用必须和引用队列( Reference queue)联合使用。
- 虚引用的主要作用是跟踪对象被垃圾回收的状态。仅仅是提供了一种确保对象被 finalize以后,做某些事情的机制。
- PhantomReference的get方法总是返回null,因此无法访问对应的引用对象。
使用它的意义在于说明一个对象已经进入 finalization阶段,可以被回收,用来实现比 finalization机制更灵活的回收操作
换句话说,设置虚引用关联的唯一目的,就是在这个对象被收集器回收的时候收到一个系统通知或者后续添加进一步的处理; - 虚引用用来管理堆外内存

ReferenceQueue 引用队列
- 对象在被回收之前要被引用队列保存一下。GC之前对象不放在队列中,GC之后才对象放入队列中。
- 【通过开启线程监听该引用队列的变化情况】就可以在对象被回收时采取相应的动作。
由于虚引用的唯一目的就是能在这个对象被垃圾收集器回收时能收到系统通知,因而创建虚引用时必须要关联一个引用队列,而软引用和弱引用则不是必须的。
这里所谓的收到系统通知其实还是通过开启线程监听该引用队列的变化情况来实现的。 - 这里还需要强调的是,
对于软引用和弱引用,当执行第一次垃圾回收时,就会将软引用或弱引用对象添加到其关联的引用队列中,然后其finalize函数才会被执行(如果没复写则不会被执行);
而对于虚引用,如果被引用对象没有复写finalize方法,则是在第一垃圾回收将该类销毁之后,才会将虚拟引用对象添加到引用队列,
如果被引用对象复写了finalize方法,则是当执行完第二次垃圾回收之后,才会将虚引用对象添加到其关联的引用队列 - 一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,
该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题,所以,推荐不要使用finalize()方法
class User{
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("我要被GC干了!");
}
}
public static void main(String[] args) throws Exception {
User user=new User();
ReferenceQueue<User> queue=new ReferenceQueue();
PhantomReference prf=new PhantomReference(user,queue);
//启动一个线程监控引用队列的变化
new Thread(()->{
for(;;){
final Reference<? extends User> u = queue.poll();
if (u!=null){
System.out.println("有对象被加入到了引用队列了!"+u);
}
}
}).start();
user=null;
//GC之前引用队列为空
System.out.println("GC之前"+queue.poll());
System.gc();
Thread.sleep(100);
//GC之后引用队列才将对象放入
System.out.println("第一次GC之后"+queue.poll());
System.gc();
Thread.sleep(100);
System.out.println("第二次GC之后"+queue.poll());
}
结果:
GC之前null
我要被GC干了!
第一次GC之后null
有对象被加入到了引用队列了!java.lang.ref.PhantomReference@549763fd
第二次GC之后java.lang.ref.PhantomReference@5aaa6d82
应用场景
软引用:SoftReference的应用场景
假如有一个应用需要读取大量的本地图片
每次读取图片都从硬盘读取会影响性能。
一次全部加载到内存中,又可能造成内存溢出。
此时,可以使用软引用解决问题;
使用一个HashMap保存图片的路径和响应图片对象关联的软引用之间的映射关系,
内存不足时,jvm会自动回收这些缓存图片对象所占用的空间,可以避免OOM。
Map<String,SoftReference<Bigmap>> imageCache=new HashMap<String,SoftReference<Bitmap>>();
https://www.bilibili.com/video/BV117411g7ib?from=search&seid=7393394991601580420
谈谈Java对象的强引用,软引用,弱引用,虚引用分别是什么的更多相关文章
- Java对象的强、软、弱和虚引用原理+结合ReferenceQueue对象构造Java对象的高速缓存器
//转 http://blog.csdn.net/lyfi01/article/details/6415726 1.Java对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变 ...
- Java对象的强、软、弱和虚引用+ReferenceQueue
Java对象的强.软.弱和虚引用+ReferenceQueue 一.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足 ...
- Java对象的强、软、弱和虚引用
本文介绍Java对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. 1.Java对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象 ...
- Java:对象的强、软、弱、虚引用
转自: http://zhangjunhd.blog.51cto.com/113473/53092 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无 ...
- Java:对象的强、软、弱和虚引用
1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK ...
- Java对象的强、软、弱和虚引用详解
1.对象的强.软.弱和虚引用 转自:http://zhangjunhd.blog.51cto.com/113473/53092/ 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无 ...
- Java:对象的强、软、弱和虚引用[转]
原文链接:http://zhangjunhd.blog.51cto.com/113473/53092/ 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法 ...
- Java:对象的强、软、弱和虚引用的区别
1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK ...
- java基础知识再学习--集合框架-对象的强、软、弱和虚引用
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://zhangjunhd.blog.51cto.com/113473/53092 本文 ...
- java中四种引用类型(对象的强、软、弱和虚引用)
对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2 ...
随机推荐
- 南宁AI项目
1.能了解并对项目整体进度情况有清晰的认识,什么时间点需要完成什么工作项. 2.认识了解项目干系人,能和客户独立沟通交流,理解现场业务,不要一问三不知,什么情况都不了. 3.能推动项目进展和问题及时处 ...
- siamese跟踪论文思考
转载自:https://zhuanlan.zhihu.com/p/34222060 通过作者在专栏里面放的几张响应图我们可以看到:SiamFC并不能区分不同的物体,图片上所有具有语义信息的物体都会得到 ...
- 1.NoSQL入门和概述
入门概述: 1.为什么要用到NoSQL a) 单机MySQL的美好年代,在90年代,一个网站的访问量一般都不大,用单个数据库完全可以轻松应付.在那个时候,更多的都是静态网页,动态交互类型的网站不多. ...
- ant design pro超详细入门教程
1.Ant Design Pro 初了解 说到ant design pro,得先了解一下ant design是个什么东西?ant design蚂蚁金服基于react打造的一个服务于企业级产品的UI框架 ...
- 如何使用Metasploit进行汽车安全性测试
前言 针对汽车的攻击和入侵是当前最前沿的领域和最热门的话题之一.随着自动驾驶汽车技术的发展,在未来这个领域将变得更加重要.作为汽车黑客快速发展的一部分,我最喜欢的黑客工具之一Metasploit也开发 ...
- STUN/TURN服务器搭建
目录 STUN/TURN服务器搭建 编译安装 配置使用 添加用户 启动server 测试 开机启动 参考 STUN/TURN服务器搭建 编译安装 编译安装 OpenSSL: sudo apt-get ...
- GVIM、VIM
全世界最好的编辑器VIM之Windows配置篇 Highlight all search pattern matches Top 10 things Vi user need to know abou ...
- win10激活密钥
专业版:W269N-WFGWX-YVC9B-4J6C9-T83GX 企业版:NPPR9-FWDCX-D2C8J-H872K-2YT43 家庭版:TX9XD-98N7V-6WMQ6-BX7FG-H8Q9 ...
- 说一下 runnable 和 callable 有什么区别?(未完成)
说一下 runnable 和 callable 有什么区别?(未完成)
- 动态规划1——最长递增子序列、最长公共子序列、最长公共子串(python实现)
目录 1. 最长递增序列 2. 最长公共子序列 3. 最长公共子串 1. 最长递增序列 给定一个序列,找出其中最长的,严格递增的子序列的长度(不要求连续). 解法一:动态规划 通过一个辅助数组记录每一 ...