概述

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. offscreenCanvas+worker+IndexedDB实现无感大量图片缓存

    一个有必要实现的需求 因为项目中需要使用canvasTexture(一个threejs3d引擎中的材质类型),绘制大量的图片,每次使用都会请求大量的oss图片资源,虽然重复请求会有磁盘缓存但毕竟这个磁 ...

  2. (Good topic)快慢指针:链表的中间结点 (3.23leetcode每日打卡)

    给定一个带有头结点 head 的非空单链表,返回链表的中间结点. 如果有两个中间结点,则返回第二个中间结点.   示例 1: 输入:[1,2,3,4,5]输出:此列表中的结点 3 (序列化形式:[3, ...

  3. 错误记录-MariaDB连接异常

    简介: 问题: C#,VS2022,mariadb-10.11.5-winx64,using MySql.Data.MySqlClient; 在执行connection.Open()时抛出异常:Sys ...

  4. 深入理解HarmonyOS UIAbility:生命周期、WindowStage与启动模式探析

    本文分享自华为云社区<深入理解HarmonyOS UIAbility:生命周期.WindowStage与启动模式探析>,作者:柠檬味拥抱. UIAbility组件概述 UIAbility组 ...

  5. Head First Java学习:第八章-接口和抽象类

    第八章:接口和抽象类 深入多态 1.抽象类:有些类不应该被初始化 在类声明前面加上抽象类的关键字,abstract. 防止类被初始化,即不能被"new"创建该类的实例(要求) 还是 ...

  6. HDU-2586 How far away?

    There are n houses in the village and some bidirectional roads connecting them. Every day peole alwa ...

  7. C++ Qt开发:StandardItemModel数据模型组件

    Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍Standar ...

  8. ElasticSearch给索引起"别名"和其重要性

    创建别名: https://www.elastic.co/guide/en/elasticsearch/reference/6.8/indices-aliases.html 我们有时候并不能确保索引库 ...

  9. Go 泛型之泛型约束

    Go 泛型之泛型约束 目录 Go 泛型之泛型约束 一.引入 二.最宽松的约束:any 三.支持比较操作的内置约束:comparable 四.自定义约束 五.类型集合(type set) 六.简化版的约 ...

  10. svelte的一些基础demo

    脚手架 Vite:vite是集成了svelte,初始化的时候选择svelte就行了. npm init vite SvelteKit:底层基于vite的更上层框架,类似于nextjs. npm cre ...