强引用

正常的引用,生命周期最长,例如 Object obj = new Object(); 当JVM内存不足时,宁可抛出OutOfMemoryError,也不愿回收存活着强引用的对象

对象还活着吗?当一个普通对象没有其他引用关系,只要超过了引用的作用域或者显示的将引用赋值为null时,你的对象就表明不是存活着,这样就会可以被GC回收了。

软引用

生命周期比强引用短,通过SoftReference类实现,可以通过get方法获取对象。

A

当JVM内存不足时会先回收软引用指向的对象,即抛出OutOfMemoryError之前,会去清理软引用对象。

软引用通常会在最后一次引用后,还能保持一段时间,默认值是根据堆剩余空间计算的。

如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用 队列中。软引用可以和引用队列(referenceQueue)联用,我们可以调用ReferenceQueue的poll()方法来检查是否有它所关心的对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。

应用场景:软引用一般用来实现内存敏感的缓存,如果有空闲内存就可以保留缓存,当内存不足时就清理掉,这样就保证使用缓存的同时不会耗尽内存,如图片缓存框架中缓存图片就是通过软引用实现。

弱引用

弱引用是通过WeakReference类实现的,它的生命周期比软引用还要短,也是通过get()方法获取对象。

JVM内存回收时,不论是否内存不足,都会回收弱引用的对象。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快回收弱引用的对象。

弱引用可以配合引用队列,如果弱引用所引用的对象被垃圾 回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

应用场景:弱引用适用于内存敏感的缓存,如ThreadLocal中的key就用到了弱引用。

幻象引用

通过PhantomReference类实现,任何时候都可以被回收,可以看作没有引用。必须和引用队列联用。无法通过get方法获取对象。

幻象引用仅仅是提供了一种确保对象被 fnalize 以后,做某些事情的机制。当垃圾回收器准备回收一个对象时,如 果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之 前采取一些程序行动。

应用场景:可用来跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾收集器回收之前会收到一条系统通知。

Object counter = new Object();
ReferenceQueue refQueue = new ReferenceQueue<>();
PhantomReference<Object> p = new PhantomReference<>(counter, refQueue);
counter = null;
Sysem.gc();
try {
// Remove是一个阻塞方法,可以指定timeout,或者选择一直阻塞
Reference<Object> ref = refQueue.remove(1000L);
if (ref != null) {
// do something
}
} catch (InterruptedException e) {
// Handle it
}

Reachability Fence

按照Java语言规范,如果一个对象没有指向强引用,就符合垃圾收集的标准。但有的场景中,对象本身并没有强引用,但是也许它的部分属性还在被使用。为了防止对象被回收,我们需要一个方法,在没有强引用情况下,通知JVM对象是在被使用的。

Java9之后,java.lang.ref.Reference给我们提供了一种方法, reachabilityFence,来声明某些没有强引用的对象,依然强可达。编程时,可以将需要reachability保障的代码段利用try-fnally包围起来,在finally里明确声明对象强可达

class Resource {
private satic ExternalResource[] externalResourceArray = ...
int myIndex; Resource(...) {
myIndex = ...
externalResourceArray[myIndex] = ...;
...
}
protected void fnalize() {
externalResourceArray[myIndex] = null;
...
}
public void action() {
try {
// 需要被保护的代码
int i = myIndex;
Resource.update(externalResourceArray[i]);
} fnally {
// 调用reachbilityFence,明确保障对象srongly reachable
Reference.reachabilityFence(this);
}
}
private static void update(ExternalResource ext) {
ext.status = ...;
}
} //非强引用
new Resource().action()

在JDK源码中,reachabilityFence大多使用在Executors或者类似新的HTTP/2客户端代码中,大部分都是异步调用的情况。

参考

《深入理解Java虚拟机》周志明

《Java核心技术36讲》杨晓峰

https://baijiahao.baidu.com/s?id=1629253892215446066&wfr=spider&for=pc

Java中的四种引用和引用队列的更多相关文章

  1. JAVA中的四种引用以及ReferenceQueue和WeakHashMap的使用示例

    简介: 本文主要介绍JAVA中的四种引用: StrongReference(强引用).SoftReferenc(软引用).WeakReferenc(弱引用).PhantomReference(虚引用) ...

  2. Java中的四种引用

    引用定义 实际上,Java中存在四种引用,它们由强到弱依次是:强引用.软引用.弱引用.虚引用.下面我们简单介绍下这四种引用: 强引用(Strong Reference):通常我们通过new来创建一个新 ...

  3. JAVA基础学习之throws和throw的区别、Java中的四种权限、多线程的使用等(2)

    1.throws和throw的区别 throws使用在函数外,是编译时的异常,throw使用在函数内,是运行时的异常 使用方法 public int method(int[] arr) throws ...

  4. JAVA中的四种JSON解析方式详解

    JAVA中的四种JSON解析方式详解 我们在日常开发中少不了和JSON数据打交道,那么我们来看看JAVA中常用的JSON解析方式. 1.JSON官方 脱离框架使用 2.GSON 3.FastJSON ...

  5. java中的四种引用方式(强引用,软引用,弱引用,虚引用)

    java内存管理主要有内存分配和内存回收,都不需要程序员负责,垃圾回收的机制主要是看对象是否有引用指向该对象. java中对象的引用主要有四种:强引用,软引用,弱引用,虚引用. Java中提供这四种引 ...

  6. Java中的四种引用类型,强引用,软引用,弱引用,虚引用

    对于Java中的垃圾回收机制来说,对象是否被回收的标准在于该对象是否被引用.因此,引用也是JVM进行内存管理的一个重要概念. Java中对象的引用一般有以下4种类型: 1强引用  2软引用  3弱引用 ...

  7. Java 中的四种引用及垃圾回收策略

    Java 中有四种引用:强引用.软引用.弱引用.虚引用: 其主要区别在于垃圾回收时是否进行回收: 1.强引用 使用最普遍的引用.如果一个对象具有强引用,那就 类似于必不可少的生活用品,垃圾回收器绝不会 ...

  8. Java入门系列 Java 中的四种引用

    Why java内存管理分为内存分配和内存回收,都不需要程序员负责,垃圾回收的机制主要是看对象是否有引用指向该对象. java对象的引用包括强引用,软引用,弱引用,虚引用 Java中提供这四种引用类型 ...

  9. Java 中的四种引用

    1.强引用(Strong Reference)在 Java 中四种引用中是“最强”的,我们平时通过 new 关键字创建的对象都属于强引用,如下面的代码: Person person = new Per ...

  10. Java中的四种引用方式

      无论是通过引用计数算法判断对象的引用数量,还是通过可达性分析算法判断对象的引用链是否可达,判定对象是否存活都与"引用"有关.在Java语言中,将引用又分为强引用.软引用.弱引用 ...

随机推荐

  1. 经典问题--php/go输出n对括号的所有组合

    问题 n对括号有多少种合法的组合,写出一个可以执行出该结果的函数: 当n=1时,输出["()"]; 当n=2时,输出["(())","()()&quo ...

  2. springboot对mybatis的整合

    1. 导入依赖 首先新建一个springboot项目,勾选组件时勾选Spring Web.JDBC API.MySQL Driver pom.xml配置文件导入依赖 <!--mybatis-sp ...

  3. Mybatis学习-GetMybatisInMyHead

    认知 Mybatis3 中文文档 练习代码 ​ MyBatis 是一款优秀的持久层框架,它支持自定义 SQL.存储过程以及高级映射.MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结 ...

  4. nginx的模块化体系结构

    nginx的模块化体系结构 nginx的内部结构是由核心部分和一系列的功能模块所组成.这样划分是为了使得每个模块的功能相对简单,便于开发,同时也便于对系统进行功能扩展.为了便于描述,下文中我们将使用n ...

  5. Docker学习(11) Dockerfile指令

    Dockerfile指令 指令格式 FROM MAINTAINER RUN EXPOSE CMD ENTRYPOINT ADD COPY VOLUME WORKDIR ENV USER ONBUILD ...

  6. RMAN-06172: no AUTOBACKUP found or specified handle is not a valid copy or piece

    问题描述:将备份集从一台主机拷贝到另外一台主机后,在通过RMAN将数据库恢复到同类机异机的时候,restore spfile一直报RMAN-06172: no AUTOBACKUP found or ...

  7. 面阿里P7,竟问这么简单的题目?

    关于作者:程序猿石头(ID: tangleithu),来自十八县贫困农村(查看我的逆袭之路),BAT某厂P7,是前大疆(无人机)技术主管,曾经也在创业公司待过,有着丰富的经验. 本文首发于微信公众号, ...

  8. spring如何集成第三方框架? 比如mybatis

    实体Bean的创建: 1: 基于class构建, 2: 构造方法构建 3: 静态工厂方法创建 4: FactoryBean构建 spring如何集成第三方框架? 比如mybatis 在mybatis中 ...

  9. 编译原理-非确定有穷自动机(nondeterministic finite automata,NFA)

    是一个五元组,M=(S,∑,f,S0,F) S:有穷状态集 ∑:输入字母表(有穷) f:f(S,α)=S' 表示从一个状态S出发,识别了一个字α后,可以到达S'这个状态集合之间的某一个状态(可能的后继 ...

  10. 【渗透实战】那些奇葩的WAF_第二期_无意发现通杀漏洞,空字节突破上传!

    /文章作者:Kali_MG1937 CSDN博客号:ALDYS4 QQ:3496925334 未经许可,禁止转载/ 该博文为本人18年左右的渗透记录,文法粗糙,技术含量极低,流水账文章,且今日不知为何 ...