Java的四种引用类型

Java四大引用彻底详解:强引用、软引用、弱引用、虚引用(实战场景 + 源码解析) Java四大引用类型详解:强、软、弱、虚引用对比分析 摘要:本文深入解析Java四大引用类型(强引用、软引用、弱引用、虚引用)的核心特性和应用场景,通过内存管理机制、源码实现和实战案例,帮助开发者优化内存使用并避免内存泄漏。强引用是默认不可回收类型,软引用适合内存敏感缓存,弱引用用于避免泄漏的映射关系,虚引用则专注于对象回收追踪。文章包含性能对比、选型决策树和生产环境避坑指南,涵盖从基础原理到企业级应用的全方位知识体系,特别适合需要解决OOM问题和优化内存管理的Java开发者。 阅读详情

Java有四种引用类型:强引用、软引用、弱引用、虚引用。

1. 强引用(StrongReference)

强引用是最常用的引用。如果一个对象具有强引用,那 GC(Gabage Collection,垃圾回收)绝不会回收它。

Object obj = new Object(); // 强引用

当内存空间不足,Java虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。如果不再需要使用对象时,要通过如下方式来弱化引用,如下:

obj = null; // 帮助垃圾收集器回收此对象

显式地设置 obj 为 null,或超出对象的生命周期范围,则 GC 认为该对象不存在引用,这时就可以回收这个对象。具体什么时候收集这要取决于 GC 的算法。

在一个方法的内部有一个强引用,这个引用保存在栈中,而真正的引用内容(Object)保存在堆中。当这个方法运行完成后就会退出方法栈,则引用内容的引用不存在,这个 Object 就会被回收。但是如果这个 obj 是全局的变量时,就需要在不用的时候赋值为 null,因为强引用不会被垃圾回收。

强引用在实际中有非常重要的用处,举个ArrayList的实现源代码:

private transient Object[] elementData;

public void clear() {
    modCount++;
    // Let gc do its work
    for (int i = 0; i < size; i++) {
        elementData[i] = null;
    }
    size = 0;
}

在 ArrayList 类中定义了一个私有的变量 elementData 数组,在调用方法清空数组时可以看到为每个数组内容赋值为null。不同于elementData = null,强引用仍然存在,避免在后续调用 add()等方法添加元素时,进行重新的内存分配。使用如 clear() 方法中释放内存的方法对数组中存放的引用类型特别适用,这样就可以及时释放内存。

2. 软引用(SoftReference)

如果一个对象只具有软引用,在内存空间足够的时候,垃圾回收器是不会回收它的;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。

String str = new String("abc"); // 强引用
SoftReference<String> softRef = new SoftReference<String>(str); // 软引用  

// 当内存不足时,等价于:
if (JVM.内存不足()) {
   str = null;  // 转换为软引用
   System.gc(); // 垃圾回收器进行回收
}

软引用在实际中有重要的应用,例如浏览器的后退按钮。按后退时,这个后退时显示的网页内容是重新进行请求还是从缓存中取出呢?这就要看具体的实现策略了。

  • 如果一个网页在浏览结束时就进行内容的回收,则按后退查看前面浏览过的页面时,需要重新构建
  • 如果将浏览过的网页存储到内存中会造成内存的大量浪费,甚至会造成内存溢出

这时候就可以使用软引用

Browser prev = new Browser(); // 获取页面进行浏览
SoftReference sr = new SoftReference(prev); // 浏览完毕后置为软引用        
if (sr.get() != null){
    rev = (Browser) sr.get(); // 还没有被回收器回收,直接获取
} else {
    prev = new Browser(); // 由于内存吃紧,所以对软引用的对象回收了
    sr = new SoftReference(prev); // 重新构建
}

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

3. 弱引用(WeakReference)

在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。

String str = new String("abc");
WeakReference<String> weakRef = new WeakReference<String>(str); // 弱引用
str = null;

// 当垃圾回收器进行扫描回收时等价于:
str = null;
System.gc(); // 垃圾回收器进行回收

// 下面的代码会让str再次变为一个强引用:
str = weakRef.get();

如果这个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么你应该用弱引用来记住此对象。

当你想引用一个对象,但是这个对象有自己的生命周期,你不想介入这个对象的生命周期,这时候你就可以使用弱引用。这个引用不会在对象的垃圾回收判断中产生任何附加的影响。

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

public class ReferenceTest {
 
    private static ReferenceQueue<VeryBig> rq = new ReferenceQueue<VeryBig>();
 
    public static void checkQueue() {
        Reference<? extends VeryBig> ref = null;
        while ((ref = rq.poll()) != null) {
            if (ref != null) {
                System.out.println("In queue: "    + ((VeryBigWeakReference) (ref)).id);
            }
        }
    }
 
    public static void main(String args[]) {
        int size = 3;
        LinkedList<WeakReference<VeryBig>> weakList = new LinkedList<WeakReference<VeryBig>>();
        for (int i = 0; i < size; i++) {
            weakList.add(new VeryBigWeakReference(new VeryBig("Weak " + i), rq));
            System.out.println("Just created weak: " + weakList.getLast());
 
        }
 
        System.gc(); 
        try { // 下面休息几分钟,让上面的垃圾回收线程运行完成
            Thread.currentThread().sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        checkQueue();
    }
}
 
class VeryBig {
    public String id;
    // 占用空间,让线程进行回收
    byte[] b = new byte[2 * 1024];
 
    public VeryBig(String id) {
        this.id = id;
    }
 
    protected void finalize() {
        System.out.println("Finalizing VeryBig " + id);
    }
}
 
class VeryBigWeakReference extends WeakReference<VeryBig> {
    public String id;
 
    public VeryBigWeakReference(VeryBig big, ReferenceQueue<VeryBig> rq) {
        super(big, rq);
        this.id = big.id;
    }
 
    protected void finalize() {
        System.out.println("Finalizing VeryBigWeakReference " + id);
    }
}

最后的输出结果为:

Just created weak: com.javabase.reference.VeryBigWeakReference@1641c0
Just created weak: com.javabase.reference.VeryBigWeakReference@136ab79
Just created weak: com.javabase.reference.VeryBigWeakReference@33c1aa
Finalizing VeryBig Weak 2
Finalizing VeryBig Weak 1
Finalizing VeryBig Weak 0
In queue: Weak 1
In queue: Weak 2
In queue: Weak 0

4. 虚引用(PhantomReference)

虚引用与其他几种引用都不同,它并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否存在该对象的虚引用,来了解这个对象是否将要被回收。可以用来作为GC回收Object的标志。

5. 总结

Java的四种引用的级别由高到低依次为:强引用  >  软引用  >  弱引用  >  虚引用

它们之间的区别如下所示:

参考文献:

  1. Java 7之基础 - 强引用、弱引用、软引用、虚引用
  2. 【知识必备】内存泄漏全解析,从此拒绝ANR,让OOM远离你的身边,跟内存泄漏say byebye

滚雪球学Java(73):Java中的引用类型: 弱引用、软引用与强引用详解 🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!! 阅读详情

相关推荐

Viobot使用教程总贴

使用教程总贴

weixin_66666206的博客 1409

Java数据类型:引用类型

引用类型,顾名思义,是用于存储对象引用(或称为句柄)的数据类型。引用类型不是类或者对象,只是变量的一种类型。当我们声明一个引用类型的变量时,该变量并不直接存储对象本身(如下图的变量obj1),而是存储了指向对象在内存中位置的一个地址(如下图的堆地址1这意味着,通过引用类型的变量,能够间接地操作对象。通过引用类型的变量对Java对象进行操作,赋予Java对象以生命力。通过本文的解析与示例,希望读者能更加深入地掌握引用类型,灵活运用这一强大工具,构建更加高效、健壮的Java应用程序。

epitomizelu的专栏 3835

Rapid SCADA MQTT

一、配置RapidSCADA 1、准备KpMqtt.dll、Jint.dll库文件,从网盘下载。 2、将以上两个文件拷贝到SCADA安装目录的Comm/KP目录下,如下: C:\SCADA\ScadaComm\KP 3、新建SCADA项目 4、新建Line 5、新建Device 6、拷贝Config目录下的KpMqtt_001.xml文件、KpMqtt_Job.js文件到项目Comm\Config下,如下示例链接 C:\SCADA\Projects\MQTTProject\Instances\Defau

mumanquan1的博客 3007

Java的4种引用类型

java为引用类型专门定义了一个类叫做。Reference是跟java垃圾回收机制息息相关的类,通过探讨Reference的实现可以更加深入的理解java的垃圾回收是怎么工作的。引用的结构图如下:引用队列是为了配合SoftReference、WeakReference、PhantomReference使用,它们三个在GC回收之前会被放到引用队列里ReferenceQueue保存下。

weixin_40482816的博客 3121

MATLAB实战:手把手教你用三频四步相移法搞定结构光三维重建(附完整代码)

本文详细介绍了如何使用MATLAB实现三频四步相移法进行高精度结构光三维重建。通过光栅图像预处理、相位计算、多频外差与相位解包裹等步骤,结合完整代码示例,帮助读者掌握从二维图像到三维点云的关键技术。该方法在工业检测和逆向工程中具有抗干扰能力强、高分辨率和鲁棒性等优势。

weixin_29201933的博客 339

Mybatis Provider注解实现批量插入

需求 借助mybatis 的provider实现一个比较通用的,批量插入数据接口。 Mapper接口 第一参数为需要批量插入的数据,第二个参数为对应实体类的class public interface BaseDao<T> { @InsertProvider(type = BaseProvider.class, method = "batchInsert") int batchInsert(@Param("lists") List<T&gt

小楼夜听雨的博客 2418

三十四、java中的引用

在系统GC时,只要发现弱引用,不管系统堆空间使用是否充足,都会回收掉只被弱引用关联的对象。弱引用对象与软引用对象的最大不同就在于,当GC在进行回收时,需要通过算法检查是否回收软引用对象,而对于弱引用对象,GC总时进行回收,弱引用对象更容易、更快被GC回收。9.相对的,软引用、弱引用和虚引用的对象是软可触及的、弱可触及的和虚可触及的,在一定条件下,都是可以被回收的。弱引用和软引用一样,在构造弱引用时,也可以指定一个引用队列,当弱引用对象被回收时,就会加入指定的引用队列,通过这个队列可以跟踪对象的回收情况。

a328062954的博客 2030

SAP-ABAP:SAP中如何查看系统表之间的关联关系?

在业务逻辑开发或者ALV开发过程中,我们通常要从系统中找出几个标准表之间的关联关系,有的是head与item,通过外键进行关联的关系。那么怎么去找到呢?以上就是具体如何产看系统表之间的关联关系的步骤,对于不同代码的业务顾问,也是必须要掌握的。

LinkStar的博客 2430

Java四种引用类型

文章目录引用类型简介对象可达性判断GC Roots对象可达性判断可达性状态类型可达性判断规则状态转换Reference类定义状态变化四种引用类型实现强引用FinalReference软引用SoftReference弱引用WeakReference虚引用PhantomReference 引用类型简介 Java开发者肯定都很熟悉java中的4种引用类型,它们从强到弱分别是: 引用类型 ...

qq_27639777的博客 1万+

Oracle 查看 rman 备份情况 SQL 语句

每天一个 DBA 小知识,助你更进一步!

LuciferLiu_DBA 3119

YOLOv11改进 | Neck篇 | 双向特征金字塔网络BiFPN助力YOLOv11有效涨点

本文给大家带来的改进机制是BiFPN双向特征金字塔网络,其是一种特征融合层的结构,也就是我们本文改进YOLOv11模型中的Neck部分,它的主要思想是通过多层级的特征金字塔和双向信息传递来提高精度。本文给大家带来的结构可以让大家自行调节网络结构大小,同时能够达到一定的轻量化效果,为什么发BiFPN呢因为它算是YOLO系列改进中的常青树了,大家可以借鉴它的双向特征思想来创新自己的Neck结构本文的BiFPN通过yaml文件配置可以让大家自行调配其结构。

Snu77的博客 9104

Java 四种引用类型

对Java 四种引用的学习,予以记录!

qq_43357394的博客 872

WCK Operation (WCK 操作)

LPDDR6 SDRAM采用双时钟系统(WCK和CK),其中WCK频率是CK的两倍。为确保数据正确传输,需通过WCK2CK同步操作使两种时钟对齐。LPDDR6支持两种同步模式:Auto-sync off模式和WCK Always on模式,可通过MR22寄存器选择。同步操作由特定命令(Read/Write/MRR等)触发,需在满足特定时序参数(如tWCKENL、tWCKPRE等)后完成。同步前必须完成WCK2CK训练,且不同操作(读取/写入/CAS)有各自的时序要求。该机制确保数据在正确时钟相位下传输,是L

李家小院 650

Java 四种引用类型介绍和演示

Java 四种引用类型介绍和演示

kerwin的博客 3859

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

【Java中四种引用类型】

弱引用(Weak Reference):是一种比软引用更弱的引用类型,它的生命周期只能存活到下一次垃圾收集之前,即只要被垃圾收集器扫描到,就会被回收。Java中的四种引用类型分别是强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference)。强引用(Strong Reference):是使用最普遍的引用类型,它直接指向对象,并且只要存在强引用,垃圾收集器就不会回收该对象。

我是Java程序员廖志伟,感谢朋友们的支持! 1439

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Java中的四种引用类型

Java中的四种引用类型

林隐的博客 751

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

《Java中的四种引用类型》

Java实际上提供了四种不同强度的引用类型,它们分别是:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和幻象引用(Phantom Reference)。当一个对象被强引用关联时,它永远不会被垃圾回收器回收,即使内存不足时,JVM宁愿抛出OutOfMemoryError也不会回收强引用对象。当JVM认为内存不足时,会回收只被软引用指向的对象。:最常见的引用类型,只要强引用存在,对象就不会被回收,可能导致内存泄漏如果管理不当。

2301_81117855的博客 446

jvmGC机制及引用类型详解(一)——java四种引用类型

本系列文章内容:jvm内存模型;javaGC机制,以及不同种GC算法关系和区别;java引用类型概念,四种引用类型的区别范围;finalize方法介绍和FinalizeReference工作机制。 这篇文章是很早之前就想写的,当时是因为在android内存工具查看内存使用时发现FinalReference这个引用没接触过,想写一篇关于FinalReference的文章,但是看着看着觉得跟GC机制...

zy_jibai 1272

java当中的四种引用类型

在Java中,有四种类型的引用,它们允许程序员以不同级别的强度来引用对象,从而影响对象的生命周期和垃圾回收的决策。这四种引用类型按照其强度从高到低排序如下: 强引用(Strong Reference) 强引用是最常见的引用类型,当一个对象被强引用持有时,只要强引用存在,垃圾回收器绝不会回收该对象。即使系统内存不足,也不会回收具有强引用的对象。除非显示地将强引用赋值为null,否则对象永远不会被当作垃圾回收。 1Object strongRef = new Object(); 软引用(

ShakespeareLies的博客 460

Java中的四种引用类型比较

1.引用的概念 引用这个概念是与JAVA虚拟机的垃圾回收有关的,不同的引用类型对应不同的垃圾回收策略或时机。 垃圾收集可能是大家感到难于理解的较难的概念之一,因为它并不能总是毫无遗漏地解决Java运行时环境中堆管理的问题。 垃圾回收的大致思路是:当Java虚拟机觉得内存不够用的时候,会触发垃圾回收操作(GC),清除无用的对象,释放内存。可是如何判断一个对象是否是垃圾呢?其中的一个方...

小伍的程序之路 625
上一篇: 懂球帝Android客户端WebView优化之路
下一篇: Android知识图谱:我们到底需要学习哪些Android知识?
Fantasy丶Lin
博客等级 码龄11年 92粉丝 59原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值