Java 四种引用类型:强引用、软引用、弱引用、虚引用
以前学习强软弱虚引用的时候,只是走马观花看看博客,并没有自己写代码去实践、去证明,导致每次看完后,过不了多久就忘了,后来下定决心,一定要自己敲敲代码,这样才能让印象更加深刻,古人云:纸上得来终觉浅,绝知此事要躬行。
Java中的四种引用
Java中有四种引用类型:强引用、软引用、弱引用、虚引用。
Java为什么要设计这四种引用
Java的内存分配和内存回收,都不需要程序员负责,都是由伟大的JVM去负责,一个对象是否可以被回收,主要看是否有引用指向此对象,说的专业点,叫可达性分析。
Java设计这四种引用的主要目的有两个:
- 可以让程序员通过代码的方式来决定某个对象的生命周期;
- 有利于垃圾回收。
强引用
强引用是最普遍的一种引用,我们写的代码,99.9999%都是强引用:
Object o = new Object();
这种就是强引用了,是不是在代码中随处可见,最亲切。
只要某个对象有强引用与之关联,这个对象永远不会被回收,即使内存不足,JVM宁愿抛出OOM,也不会去回收。
那么什么时候才可以被回收呢?当强引用和对象之间的关联被中断了,就可以被回收了。
我们可以手动把关联给中断了,方法也特别简单:
o = null;
我们可以手动调用GC,看看如果强引用和对象之间的关联被中断了,资源会不会被回收,为了更方便、更清楚的观察到回收的情况,我们需要新写一个类,然后重写finalize方法,下面我们来进行这个实验:
public class Student {@Overrideprotected void finalize() throws Throwable {System.out.println("Student 被回收了");}
}
public static void main(String[] args) {Student student = new Student();student = null;System.gc();
}
运行结果:
Student 被回收了
可以很清楚的看到资源被回收了。
当然,在实际开发中,千万不要重写finalize方法
在实际的开发中,看到有一些对象被手动赋值为NULL,很大可能就是为了“特意提醒”JVM这块资源可以进行垃圾回收了。
软引用
下面先来看看如何创建一个软引用:
SoftReference<Student>studentSoftReference=new SoftReference<Student>(new Student());
软引用就是把对象用SoftReference包裹一下,当我们需要从软引用对象获得包裹的对象,只要get一下就可以了:
SoftReference<Student>studentSoftReference=new SoftReference<Student>(new Student());Student student = studentSoftReference.get();System.out.println(student);
软引用有什么特点呢:
当内存不足,会触发JVM的GC,如果GC后,内存还是不足,就会把软引用的包裹的对象给干掉,也就是只有在内存不足,JVM才会回收该对象。
还是一样的,必须做实验,才能加深印象:
SoftReference<byte[]> softReference = new SoftReference<byte[]>(new byte[1024*1024*10]);System.out.println(softReference.get());System.gc();System.out.println(softReference.get());byte[] bytes = new byte[1024 * 1024 * 10];System.out.println(softReference.get());
我定义了一个软引用对象,里面包裹了byte[],byte[]占用了10M,然后又创建了10Mbyte[]。
运行程序,需要带上一个参数:
-Xmx20M
代表最大堆内存是20M。
运行结果:
[B@11d7fff
[B@11d7fff
null
可以很清楚的看到手动完成GC后,软引用对象包裹的byte[]还活的好好的,但是当我们创建了一个10M的byte[]后,最大堆内存不够了,所以把软引用对象包裹的byte[]给干掉了,如果不干掉,就会抛出OOM。
软引用到底有什么用呢?比较适合用作缓存,当内存足够,可以正常的拿到缓存,当内存不够,就会先干掉缓存,不至于马上抛出OOM。
弱引用
弱引用的使用和软引用类似,只是关键字变成了WeakReference:
WeakReference<byte[]> weakReference = new WeakReference<byte[]>(new byte[1024*1024*10]);System.out.println(weakReference.get());
弱引用的特点是不管内存是否足够,只要发生GC,都会被回收:
WeakReference<byte[]> weakReference = new WeakReference<byte[]>(new byte[1]);System.out.println(weakReference.get());System.gc();System.out.println(weakReference.get());
运行结果:
[B@11d7fff
null
可以很清楚的看到明明内存还很充足,但是触发了GC,资源还是被回收了。
弱引用在很多地方都有用到,比如ThreadLocal、WeakHashMap。
虚引用
虚引用又被称为幻影引用,我们来看看它的使用:
ReferenceQueue queue = new ReferenceQueue();PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1], queue);System.out.println(reference.get());
虚引用的使用和上面说的软引用、弱引用的区别还是挺大的,我们先不管ReferenceQueue 是个什么鬼,直接来运行:
null
竟然打印出了null,我们来看看get方法的源码:
public T get() {return null;}
这是几个意思,竟然直接返回了null。
这就是虚引用特点之一了:无法通过虚引用来获取对一个对象的真实引用。
那虚引用存在的意义是什么呢?这就要回到我们上面的代码了,我们把代码复制下,以免大家再次往上翻:
ReferenceQueue queue = new ReferenceQueue();PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1], queue);System.out.println(reference.get());
创建虚引用对象,我们除了把包裹的对象传了进去,还传了一个ReferenceQueue,从名字就可以看出它是一个队列。
虚引用的特点之二就是 虚引用必须与ReferenceQueue一起使用,当GC准备回收一个对象,如果发现它还有虚引用,就会在回收之前,把这个虚引用加入到与之关联的ReferenceQueue中。
我们来用代码实践下吧:
ReferenceQueue queue = new ReferenceQueue();List<byte[]> bytes = new ArrayList<>();PhantomReference<Student> reference = new PhantomReference<Student>(new Student(),queue);new Thread(() -> {for (int i = 0; i < 100;i++ ) {bytes.add(new byte[1024 * 1024]);}}).start();new Thread(() -> {while (true) {Reference poll = queue.poll();if (poll != null) {System.out.println("虚引用被回收了:" + poll);}}}).start();Scanner scanner = new Scanner(System.in);scanner.hasNext();}
运行结果:
Student 被回收了
虚引用被回收了:java.lang.ref.PhantomReference@1ade6f1
我们简单的分析下代码:
第一个线程往集合里面塞数据,随着数据越来越多,肯定会发生GC。
第二个线程死循环,从queue里面拿数据,如果拿出来的数据不是null,就打印出来。
从运行结果可以看到:当发生GC,虚引用就会被回收,并且会把回收的通知放到ReferenceQueue中。
虚引用有什么用呢?在NIO中,就运用了虚引用管理堆外内存。
Java 四种引用类型:强引用、软引用、弱引用、虚引用相关推荐
- java中四种引用类型(对象的强、软、弱和虚引用)
2019独角兽企业重金招聘Python工程师标准>>> 对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有 ...
- Java:对象的强、软、弱和虚引用
见:http://zhangjunhd.blog.51cto.com/113473/53092 maven/Java/web/bootstrap/dataTable/app开发QQ群:56686262 ...
- 软引用和弱引用的区别_强、软、弱、虚引用的区别和使用
原文阅读: 强.软.弱.虚引用的区别和使用mp.weixin.qq.com Java提供了四种级别的应用类型:强引用.软引用.弱引用及虚引用.那么这四种引用类型有什么区别呢? 首先我们通过一张图来看 ...
- 对象的强、软、弱和虚引用
本文介绍对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有 ...
- java-基础-强、软、弱、虚引用
Java的四种引用,强弱软虚,用到的场景. JDK1.2之前只有强引用,其他几种引用都是在JDK1.2之后引入的. 强引用(Strong Reference) 最常用的引用类型,如Object obj ...
- jvm系列 (四) ---强、软、弱、虚引用
java引用 目录 jvm系列(一):jvm内存区域与溢出 jvm系列(二):垃圾收集器与内存分配策略 jvm系列(三):锁的优化 我的博客目录 为什么将引用分为不同的强度 因为我们需要实现这样一种情 ...
- JVM 学习(2)—简单理解Java 四大引用(强、软、弱、虚)
一.Java 引用概述 Java 中出现四种引用是为了更加灵活地管理对象的生命周期,以便在不同场景下灵活地处理对象的回收问题.不同类型的引用在垃圾回收时的处理方式不同,可以用来实现不同的垃圾回收策略. ...
- JAVA 四种引用类型和垃圾回收器
JAVA 四种引用类型 强引用 在 Java 中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用.当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的 ...
- Java对象引用四个级别(强、软、弱、虚)
转载自 Java对象引用四个级别(强.软.弱.虚) 最近,高级Java技术栈微信群中,有一些猿友在讨论JVM中对象的周期问题,有谈到引用的级别,现在为大家做个总结吧,虽然大多数公司并没有意识或者用到这 ...
- 【Java】Java对象引用四个级别(强、软、弱、虚)
文章目录 1.概述 强引用(StrongReference) 软引用(SoftReference) 弱引用(WeakReference) 虚引用(PhantomReference) 2. 扩展阅读 1 ...
最新文章
- UIAlertview改变按钮位置 大小
- 第一次作业:阅读优秀博文谈感想
- iOS-CoreImage简单使用
- [云炬创业基础笔记]第四章测试18
- HDU - 1079 Calendar Game(博弈打表sg函数)
- java 获取键盘输入法_Java中接收键盘输入的三种方法
- Linux 更改共享内存tmpfs的大小
- 百度360之争的背后
- Log Explorer 使用简介转
- 盈不足术与老鼠打洞问题的近似解
- linux xfs文件系统故障修复,xfs文件系统修复方法
- java实现旅行商问题_Java中旅行商问题的强力算法
- 水星无线路由启动dhcp服务器,水星无线路由器桥接设置桥接(图文详解) | 192.168.1.1登陆页面...
- 10个可以让你达到谷歌首页的谷歌SEO技巧
- ppt密码怎么设置,ppt权限密码如何破解?
- .NET c#音乐播放器
- js正则效验不能全为数字、字母 不超过50字符
- 开启 MySQL 慢查询日志
- RSA算法和RSA数字签名算法
- 在Ubuntu上创建Git仓库并上传到GitHub
热门文章
- NC:蜜蜂肠道微生物的多样性
- Ecol. Lett. | 生态学实验设计中“梯度实验”和“重复实验”的抉择
- 漫谈16S的前世今生
- 多媒体计算机技术在教学中的应用,【浅谈多媒体计算机技术在中学物理教学中的应用】计算机技术是什么...
- 查找字符串末尾含关键字_Excel教程:用find函数带关键字提取杂乱文本
- python使用sklearn中的make_classification函数生成分类模型(classification)需要的仿真数据、使用pandas查看生成数据的特征数据、目标数据
- R语言可视化分面图、假设检验、单变量分组多水平t检验并指定参考水平、可视化单变量分组多水平分面箱图(faceting boxplot)并添加显著性水平、指定显著性参考水平
- 主成分分析(Principle Component Analysis)PCA的核心思想是什么?PCA算法的优缺点?增量PCA模型, 随机PCA, 模型、 核化PCA分别是什么?使用时如何选择?
- pandas读写结构化数据(read_csv,read_table, read_excel, read_html, read_sql)
- pip 更新失败报[no module named pip]修复方法