概述

Java 中的引用类似 C 语言中的指针,指向一个对象,比如:

// person 就是指向 Person 实例“张三”的引用
Person person = new Person("张三");

在 JDK1.2 以前,Java 里的引用是很传统的定义:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称该 reference 数据是代表某块内存、某个对象的引用

这种定义当然没有什么不对,但现在看来显得太狭隘了,比如我们希望描述一类对象:当内存空间足够时,能保留在内存中,如果内存空间在进行了垃圾收集后仍然紧张,则可以抛弃这些对象,很多系统的缓存功能都符合这样的应用场景

JDK1.2 对引用的概念作了补充,将引用分为强引用(Strongly Reference)、软引用(SoftReference)、弱引用(Weak Reference)和虚引用(Phantom Reference),强度依次减弱

强引用

Java 中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用。类似 Object obj = new Object()

当一个对象被强引用变量引用时,除非超过了引用的作用域或者显示地将相应强引用赋值为 null,否则是不可能被垃圾回收器回收的

软引用

软引用用来描述一些有用但非必须的对象,此类对象只有在进行一次垃圾收集仍然没有足够内存时,才会在第二次垃圾收集时被回收,需要用 java.lang.ref.SoftReference 类来实现

public class SoftRefenenceDemo {

    public static void main(String[] args) {
softRefMemoryEnough();
System.out.println("------------");
softRefMemoryNotEnough();
} private static void softRefMemoryEnough() {
Object o1 = new Object();
SoftReference<Object> s1 = new SoftReference<Object>(o1);
System.out.println(o1); // java.lang.Object@2503dbd3
System.out.println(s1.get()); // java.lang.Object@2503dbd3 o1 = null;
System.gc(); System.out.println(o1); // null
System.out.println(s1.get()); // java.lang.Object@2503dbd3
} /**
* JVM配置 -Xms5m -Xmx5m ,故意 new 一个大对象,使内存不足产生 OOM,看软引用回收情况
*/
private static void softRefMemoryNotEnough() {
Object o1 = new Object();
SoftReference<Object> s1 = new SoftReference<Object>(o1);
System.out.println(o1); // java.lang.Object@4b67cf4d
System.out.println(s1.get()); // java.lang.Object@4b67cf4d o1 = null; try {
byte[] bytes = new byte[10 * 1024 * 1024];
} catch(Error e) {
e.printStackTrace();
} System.out.println(o1); // null
System.out.println(s1.get()); // null
}
}

弱引用

弱引用用来描述那些非必须对象,但它的强度比软引用更弱一些。被软引用关联的对象只能生存到下一次垃圾收集发生为止,当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象,需要用 java.lang.ref.WeakReference 类来实现

public class WeakReferenceDemo {

    public static void main(String[] args) {
Object o1 = new Object();
WeakReference<Object> w1 = new WeakReference<Object>(o1); System.out.println(o1); // java.lang.Object@7440e464
System.out.println(w1.get()); // java.lang.ref.WeakReference@49476842 o1 = null;
System.gc(); System.out.println(o1); // null
System.out.println(w1.get()); // null
}
}

虚引用

虚引用,顾名思义,就是形同虚设,与其他几种引用都不太一样,一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列(RefenenceQueue)联合使用。虚引用的主要作用是跟踪对象垃圾回收的状态,仅仅是提供了一种确保对象被 finalize 以后,收到一个系统通知或者后续添加进一步的处理

public class PhantomReferenceDemo {

    public static void main(String[] args) throws InterruptedException {
Object o1 = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
PhantomReference<Object> phantomReference = new PhantomReference<Object>(o1,referenceQueue); System.out.println(o1); // java.lang.Object@7440e464
System.out.println(referenceQueue.poll()); // null
System.out.println(phantomReference.get()); // null o1 = null;
System.gc();
Thread.sleep(3000); System.out.println(o1); // null
System.out.println(referenceQueue.poll()); // java.lang.ref.PhantomReference@49476842
System.out.println(phantomReference.get()); // null
} }

ReferenceQueue 是用来配合引用工作的,没有ReferenceQueue 一样可以运行。SoftReference、WeakReference、PhantomReference 都有一个可以传递 ReferenceQueue 的构造器。创建引用的时候,可以指定关联的队列,当 GC 释放对象内存的时候,会将引用加入到引用队列。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动,这相当于是一种通知机制。当关联的引用队列中有数据的时候,意味着指向的堆内存中的对象被回收。通过这种方式,JVM 允许我们在对象被销毁后,做一些我们自己想做的事情

Java 四种引用类型(强引用、软引用、弱引用、虚引用)的更多相关文章

  1. java中四种引用类型(对象的强、软、弱和虚引用)

    对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2 ...

  2. Java中四种引用:强、软、弱、虚引用

    这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...

  3. Java对象的强、软、弱和虚引用+ReferenceQueue

    Java对象的强.软.弱和虚引用+ReferenceQueue 一.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足 ...

  4. Java:对象的强、软、弱、虚引用

    转自: http://zhangjunhd.blog.51cto.com/113473/53092 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无 ...

  5. Java:对象的强、软、弱和虚引用

    1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK ...

  6. Java对象的强、软、弱和虚引用详解

    1.对象的强.软.弱和虚引用 转自:http://zhangjunhd.blog.51cto.com/113473/53092/ 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无 ...

  7. java基础知识再学习--集合框架-对象的强、软、弱和虚引用

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://zhangjunhd.blog.51cto.com/113473/53092 本文 ...

  8. Java对象的强、软、弱和虚引用原理+结合ReferenceQueue对象构造Java对象的高速缓存器

    //转 http://blog.csdn.net/lyfi01/article/details/6415726 1.Java对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变 ...

  9. Java:对象的强、软、弱和虚引用[转]

    原文链接:http://zhangjunhd.blog.51cto.com/113473/53092/ 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法 ...

  10. Java:对象的强、软、弱和虚引用的区别

    1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK ...

随机推荐

  1. crazy

    说实话刚拿到题目我是一点思路没有,因为我感觉伪代码里面的函数名都太奇怪了,怀疑应该不是在这方面出题,结果看了wp发现就是在这方面出题... 这种情况我是从后面开始看的,看看出现正确提示会需要什么条件 ...

  2. go并发 - goroutine

    概述 Go并发模型独树一帜,简洁.高效.Go语言最小执行单位称为协程(goroutine),运行时可以创建成千万上个协程,这在Java.C等线程模型中是不可想象的,并发模型是Go的招牌能力之一.很多文 ...

  3. 七天.NET 8操作SQLite入门到实战 - SQLite 简介

    什么是SQLite? SQLite是一个轻量级的嵌入式关系型数据库,它以一个小型的C语言库的形式存在.它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可 ...

  4. python中的post请求

    用python来验证接口正确性,主要流程有4步: 1 设置url 2 设置消息头 3 设置消息体 4 获取响应 5 解析相应 6 验证数据 Content-Type的格式有四种:分别是applicat ...

  5. git 同时推送多个远程仓库

    今天遇到个git的问题:需要同时提交到两个远程仓库 解决方法: git add . git commit -m '提交信息' git remote -v git remote add old_orig ...

  6. SFX的妙用——如何在不安装软件的情况下打开自定义格式文件?

    前段时间看到群友讨论压缩包能不能运行,想起了N年前用自解压文件SFX实现的一个"需求":在没有安装任何应用软件的Windows(当时还要支持XP)上能双击打开自定义格式的文件.当时 ...

  7. 公司敏感数据被上传Github,吓得我赶紧改提交记录

    大家好,我是小富- 说个事吧!最近公司发生了一个事故,有同事不小心把敏感数据上传到了GitHub上,结果被安全部门扫描出来了.这件事导致公司对所有员工进行了一次数据安全的培训.对于这个事我相信,有点工 ...

  8. 使用Netty实现文件传输的HTTP服务器和客户端

    现在我们来用netty实现文件传输的HTTP服务器和客户端 pom依赖文件: <?xml version="1.0" encoding="UTF-8"?& ...

  9. [THUPC 2023 初赛] 背包

    题目描述 本题中,你需要解决完全背包问题. 有 \(n\) 种物品,第 \(i\) 种物品单个体积为 \(v_i\).价值为 \(c_i\). \(q\) 次询问,每次给出背包的容积 \(V\),你需 ...

  10. Elasticsearch安装ik分词器,并配置扩展词典

    1.首先安装好elasticsearch,这里我用的是docker安装 2.去GitHub下载ik分词器,GitHub地址 3.下好了解压 4.使用远程客户端工具(我用的是finalShell)将整个 ...