Java (强/弱/软/虚)引用
一、整体架构

二、强引用(默认支持)
当内存不足,JVM 开始垃圾回收,对于强引用的对象,就算是出现了 OOM 也不会对该对象进行回收,死都不收。强引用是我们最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还“活着”,垃圾回收器不会碰这种对象。在Java 中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用。当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的,即使该对象以后永远都不会被用到 JVM 也不会回收。因此强引用是造成内存泄漏的主要原因之一。对于一个普通对象,如果没有其他引用关系,只要超过引用的作用域或者显示地将强应用设置为null,一般就可以被垃圾收集。(当然具体回收时机是要看垃圾收集策略)。
1 public class ReferenceDemo {
2 public static void main(String[] args) {
3 //o1 强引用(默认)
4 Object o1 = new Object();
5 //o2 引用赋值
6 Object o2 = o1;
7 //将o1 置为null
8 o1 = null;
9 //触发垃圾回收,回收o1
10 System.gc();
11 //查看 o2 是否有变化
12 //输出结果:java.lang.Object@5305068a 说明o2 没有被回收,属于强引用
13 System.out.println(o2);
14 }
15 }
三、软引用
软引用是一种相对强引用弱化了一些的引用,需要用 java.lang.ref.SoftReference 类来实现,可以让对象豁免一些垃圾收集。对于弱引用来说:
【1】当系统内存充足时它不会被回收;
1 public class ReferenceDemo {
2 public static void main(String[] args) {
3 //o1 强引用(默认)
4 Object o1 = new Object();
5 //o2 引用赋值 ************重点***************
6 SoftReference<Object> softReference = new SoftReference<>(o1);
7 //java.lang.Object@5305068a
8 System.out.println(o1);
9 //将o1 置为null
10 o1 = null;
11 //触发垃圾回收,回收o1
12 System.gc();
13 //查看 o2 是否有变化
14 //输出结果:java.lang.ref.SoftReference@5305068a 说明softReference 没有被回收,因为内存充足
15 System.out.println(softReference.get());
16 //输出结果:null
17 System.out.println(o1);
18 }
19 }
【2】当系统内存不充足时它会被回收;代码演示:准备工作,设置内存大小为10m,具体配置如下:

1 @org.junit.Test
2 public void softReference(){
3 //o1 强引用(默认)
4 Object o1 = new Object();
5 //o2 引用赋值
6 SoftReference<Object> softReference = new SoftReference<>(o1);
7 //将o1 置为null
8 o1 = null;
9 try {
10 //模拟内存不足,我们通过 Xms和Xmx分配10M 的内存
11 byte[] bytes = new byte[20*1024*1024];
12 }catch (Exception e){
13 e.printStackTrace();
14 }finally {
15 //通过get 方法获取应用对象,输出结果为:null 说明内存不足时对此进行了回收
16 System.out.println(softReference.get());
17 }
18 }
软引用通常用于对内存敏感的程序中,比如高速缓冲就有用到软引用,内存够用的时候就保留,不够就回收!
四、弱引用
弱引用需要用 java.lang.ref.WeakReference 类实现,它比软引用的生存期更短,对于只有软引用的对象来说,只要垃圾回收机制一运行,不管JVM 内存是否足够,都会回收该对象占用的内存。
1 @org.junit.Test
2 public void weakReference(){
3 //o1 强引用(默认)
4 Object o1 = new Object();
5 //o2 引用赋值
6 WeakReference<Object> weakReference = new WeakReference<>(o1);
7 //输出结果:java.lang.Object@1b701da1
8 System.out.println(weakReference.get());
9 //将o1 置为null
10 o1 = null;
11 System.gc();
12 //通过get 方法获取应用对象,输出结果为:null 说明只要进行过gc 就可能被回收
13 System.out.println(weakReference.get());
14 }
五、虚引用
虚引用需要 java.lang.ref.PhantomReference 类来实现。顾名思义,就是形同虚设,与其它几种引用不同,虚引用并不会决定对象的声明周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收,它不能单独使用也不能通过它访问对象,虚引用必须和引用队列(ReferenceQueue)联合使用。
虚引用的主要作用是跟踪对象被垃圾回收的状态,仅仅是提供一种确保对象被 finalize 以后,做某些事情的机制。PhantomReference 的 get方法总是返回 null,因此无法访问对应的引用对象。其意义在于说明一个对象已经进入 finalization 阶段,可以被 gc 回收,用来实现比 finalization 机制更灵活的回收操作。
换句话说,设置虚拟引用的唯一目的,就是在这个对象被收集器回收的时候收到一个系统通知或者后续添加进一步处理。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。
1 @org.junit.Test
2 public void phantomReference(){
3 //o1 强引用(默认)
4 Object o1 = new Object();
5 //引用队列
6 ReferenceQueue referenceQueue = new ReferenceQueue();
7 //创建虚引用
8 PhantomReference phantomReference = new PhantomReference<>(o1, referenceQueue);
9 System.out.println("GC 之前===================");
10 System.out.println("o1 = "+o1);
11 System.out.println("phantomReference = "+phantomReference.get());
12 System.out.println("referenceQueue = "+referenceQueue.poll());
13
14 //垃圾回收
15 o1=null;
16 System.gc();
17
18 System.out.println("GC 之后===================");
19 System.out.println("o1 = "+o1);
20 System.out.println("phantomReference = "+phantomReference.get());
21 System.out.println("referenceQueue = "+referenceQueue.poll());
22 }
输出结果展示:

Java (强/弱/软/虚)引用的更多相关文章
- 0030 Java学习笔记-面向对象-垃圾回收、(强、软、弱、虚)引用
垃圾回收特点 垃圾:程序运行过程中,会为对象.数组等分配内存,运行过程中或结束后,这些对象可能就没用了,没有变量再指向它们,这时候,它们就成了垃圾,等着垃圾回收程序的回收再利用 Java的垃圾回收机制 ...
- Java:对象的强、软、弱、虚引用
转自: http://zhangjunhd.blog.51cto.com/113473/53092 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无 ...
- Java中四种引用:强、软、弱、虚引用
这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...
- 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对象的强、软、弱和虚引用原理+结合ReferenceQueue对象构造Java对象的高速缓存器
//转 http://blog.csdn.net/lyfi01/article/details/6415726 1.Java对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变 ...
- Java:对象的强、软、弱和虚引用[转]
原文链接:http://zhangjunhd.blog.51cto.com/113473/53092/ 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法 ...
- Java对象的强、软、弱和虚引用+ReferenceQueue
Java对象的强.软.弱和虚引用+ReferenceQueue 一.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足 ...
- Java:对象的强、软、弱和虚引用的区别
1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK ...
随机推荐
- Tomcat9启动闪退或者在windows服务中启动异常以及启动日志乱码问题
首先虽然jdk6以后不需要在环境变量中额外配置jre了,但是我在tomcat的bin下startup.bat时启动时发现 可见用到了JRE_HOME,所以你需要去额外配置一下,否则会出现另外一种错误, ...
- 关于css选择器的一点点记录
<!-- 选择器: #id..class.标签.>子代. 后代.+紧跟一个.~紧跟所有.:(效果)伪类 --> <!-- 效果选择器常用属性: ...
- bzoj 4817
LCT好题 首先我们考虑实际询问的是什么: 从LCT的角度考虑,如果我们认为一开始树上每一条边都是虚边,把一次涂色看作一次access操作,那么询问的实际就是两个节点间的虚边数量+1和子树中的最大虚边 ...
- 为什么javac后加.java,java后不加.class?
Javac和java命令的用法:javac需要文件,Java需要执行类或jar文件javac用法: java用法 例子 Java命令后的"test.Test.class"会被认为是 ...
- zynq 中断
#include "stdio.h"#include "xparameters.h"#include "xgpiops.h"#include ...
- docker知识篇
什么是Docker?Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的.可移植的.自给自足的容器.开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机).b ...
- LEETCODE 数组嵌套
题目:数组嵌套 索引从0开始长度为N的数组A,包含0到N - 1的所有整数.找到最大的集合S并返回其大小,其中 S[i] = {A[i], A[A[i]], A[A[A[i]]], ... }且遵守以 ...
- CentOS7安装 Redis5 单实例
1.下载redis下载地址在:redis.io比如把Redis安装到/usr/local/soft/ cd /usr/local/soft/ wget http://download.redis.io ...
- [整理]String用法/转换substring
substring(a)从a开始 substring(a,b) [a,b] s=123456789 s.substring(3):456789 s.substring(0,3):1234
- Excel 去除合并并保留原值的办法
部分Excel中,对行进行了合并.这个方便展示,但是筛选后数据展示会出现问题,需要去除合并,并在每行中保留原来的值. 1.先选择整行,并"取消单元格合并" 操作后出现大量的空值行. ...