老徐和阿珍的故事:强引用、软引用、弱引用、虚引用,傻傻分不清楚

人物背景
老徐,男,本名徐福贵,从事Java相关研发工作多年,职场老油条,摸鱼小能手,虽然岁数不大但长的比较着急,人称老徐。据说之前炒某币败光了所有家产,甚至现在还有欠债。
阿珍,女,本名陈家珍,刚刚入职不久的实习生,虽然是职场菜鸟但聪明好学。据说是学校的四大校花之一,追求她的人从旺角排到了铜锣湾,不过至今还单身。

阿珍:”老徐,你这茶杯了泡的什么?红红的。”
老徐:”这是枸杞呀。”
阿珍:”枸杞?你最近什么干多了,这么 !”
老徐:”怎么可能?看我这身体,不 的好吧!”
阿珍一脸坏笑地说:”那就是 了。”
老徐的老脸一红,辩解到:”我这是养养生,我很 的,好吧。”
看着老徐的窘态,阿珍笑出来声。老徐起身刚要走,阿珍一把拽住老徐,说:”跟你开玩笑呢,问你个正事,我一直分不清Java的强引用、软引用、弱引用、虚引用,给我讲讲呗。”
老徐立刻自信满满的坐下,说:”那你可问对人了,我对这方面颇有研究。这四种引用级别由高到低依次是:强引用、软引用、弱引用、虚引用。”

强引用是Java中最常见的引用方式,99.99%用的都是强引用。我们创建了一个对象,并把它赋值给某一个变量,我们就可以通过这个变量操作实际的对象了,比如:

String name = "万猫学社";
System.out.println(name);

当一个对象被一个或者多个变量强引用时,它就是处于一个可达状态,不会被垃圾回收机制回收掉。即使在内存不够的情况下,Java虚拟机宁愿抛出OutOfMemoryError异常,也不会回收这样的对象。

软引用是通过 SoftReference类进行实现的,当一个对象只有软引用的时候,Java虚拟机的垃圾回收机制运行后,当内存空间足够时,它就不会被回收掉;当内存空间不够时,它就会被回收掉。比如:

SoftReference softReference = new SoftReference<>(new byte[1024 * 1024 * 5]);
System.out.println("垃圾回收前:" + softReference.get());

//建议Java虚拟机执行垃圾回收
System.gc();

System.out.println("内存足够时,垃圾回收后:" + softReference.get());

byte[][] bytes = new byte[10][];
for (int i = 0; i < 10; i++) {
    bytes[i] = new byte[1024 * 1024 * 1];
}

System.out.println("内存不足时,垃圾回收后:" + softReference.get());

在运行时加入 -Xmx15M (设置Java堆的最大内存为15M)和 -XX:+PrintGC(开启垃圾回收的日志打印)参数,我们就可以看到下面的结果:

&#x5783;&#x573E;&#x56DE;&#x6536;&#x524D;&#xFF1A;[B@1de0aca6
[GC (System.gc())  9173K->6495K(15872K), 0.0033951 secs]
[Full GC (System.gc())  6495K->6434K(15872K), 0.0149312 secs]
&#x5185;&#x5B58;&#x8DB3;&#x591F;&#x65F6;&#xFF0C;&#x5783;&#x573E;&#x56DE;&#x6536;&#x540E;&#xFF1A;[B@1de0aca6
[GC (Allocation Failure)  9588K->9570K(15872K), 0.0013485 secs]
[Full GC (Ergonomics)  9570K->9506K(15872K), 0.0032467 secs]
[Full GC (Ergonomics)  12659K->12549K(15872K), 0.0083257 secs]
[Full GC (Ergonomics)  13573K->13573K(15872K), 0.0043525 secs]
[Full GC (Allocation Failure)  13573K->8435K(15872K), 0.0065695 secs]
&#x5185;&#x5B58;&#x4E0D;&#x8DB3;&#x65F6;&#xFF0C;&#x5783;&#x573E;&#x56DE;&#x6536;&#x540E;&#xFF1A;null

可以看到,当内存空间足够时,软引用的对象不会被回收掉;当内存空间不够时,软引用的对象就会被回收掉。

弱引用是通过 WeakReference类进行实现的,弱引用和软引用很类似,但是比软引用的级别更低。当一个对象只有弱引用的时候,Java虚拟机的垃圾回收机制运行后,无论内存是否足够,它都会被回收掉。比如:

WeakReference weakReference = new WeakReference<>(new byte[1024 * 1024 * 5]);
System.out.println("垃圾回收前:" + weakReference.get());

//建议Java虚拟机执行垃圾回收
System.gc();

System.out.println("内存足够时,垃圾回收后:" + weakReference.get());

同样的,在运行时加入 -Xmx15M (设置Java堆的最大内存为15M)和 -XX:+PrintGC(开启垃圾回收的日志打印)参数,我们就可以看到下面的结果:

&#x5783;&#x573E;&#x56DE;&#x6536;&#x524D;&#xFF1A;[B@1de0aca6
[GC (System.gc())  9150K->6481K(15872K), 0.0015689 secs]
[Full GC (System.gc())  6481K->1317K(15872K), 0.0062846 secs]
&#x5185;&#x5B58;&#x8DB3;&#x591F;&#x65F6;&#xFF0C;&#x5783;&#x573E;&#x56DE;&#x6536;&#x540E;&#xFF1A;null

可以看到,即使在内存足够的时候,弱引用的对象也会被回收掉。

虚引用通过 PhantomReference类进行实现的,虚引用完全类似于没有引用。如果一个对象只有一个虚引用,那么它就是和没有引用差不多。虚引用主要用于跟踪对象被垃圾回收的状态,虚引用不能单独使用,必须和引用队列(ReferenceQueue)一起使用。我们不能通过虚引用获取到被引用的对象,只有在该对象被回收后,该对象的虚引用会被放到和虚引用关联的引用队列中,比如:

ReferenceQueue referenceQueue = new ReferenceQueue();
PhantomReference phantomReference = new PhantomReference<>(new byte[1024 * 1024 * 5], referenceQueue);

System.out.println("垃圾回收前:" + phantomReference.get());

byte[][] bytes = new byte[10][];
for (int i = 0; i < 5; i++) {
    bytes[i] = new byte[1024 * 1024 * 1];
}

System.out.println("垃圾回收后:" + referenceQueue.poll());

同样的,在运行时加入 -Xmx15M (设置Java堆的最大内存为15M)和 -XX:+PrintGC(开启垃圾回收的日志打印)参数,我们就可以看到下面的结果:

&#x5783;&#x573E;&#x56DE;&#x6536;&#x524D;&#xFF1A;null
[GC (Allocation Failure)  9068K->6517K(15872K), 0.0019272 secs]
[GC (Allocation Failure)  9713K->9621K(15872K), 0.0015966 secs]
[Full GC (Ergonomics)  9621K->9506K(15872K), 0.0092758 secs]
&#x5783;&#x573E;&#x56DE;&#x6536;&#x540E;&#xFF1A;java.lang.ref.PhantomReference@1de0aca6

可以看到,不能通过虚引用获取到被引用的对象,在该对象被回收后,可以从引用队列中获取对应的虚引用。

老徐看着阿珍一脸懵逼的样子说:”小朋友,你是不是有很多问号?””信息量有点大,我得慢慢消化消化。”阿珍回答到。老徐说:”没关系,我给你简单总结一下,很方便理解和记忆。”

  • 强引用:Java中最常见的引用方式,即使内存不足也不会被垃圾回收。
  • 软引用:当内存不足时,垃圾回收机制运行后对象被回收。
  • 弱引用:无论内存是否足够,垃圾回收机制运行后对象被回收。
  • 虚引用:主要用于跟踪对象被垃圾回收的状态,必须和引用队列一起使用。

最后,谢谢你这么帅,还给我 点赞关注

Original: https://www.cnblogs.com/heihaozi/p/16059578.html
Author: 万猫学社
Title: 老徐和阿珍的故事:强引用、软引用、弱引用、虚引用,傻傻分不清楚

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/580942/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • kotlin 圆形进度条

    kotlin版的自定义圆形进度条 大多数启动页都会带个进度条加载样式,所以就自己用kotlin重新写了一个,如果真的要很炫酷还是有很多东西可以附加的 一个简单的进度条基本组成就是一…

    Java 2023年6月7日
    082
  • JAVA的类加载过程

    我们详细讲解一下Java虚拟机中类加载的全过程,也就是加载、验证、准备、解析和初始化这5个阶段所执行的具体动作。 一、加载“加载”是”类加载&#…

    Java 2023年5月29日
    088
  • SpringBoot启动过程(生命周期及事件)概述

    总结: ======================== 详见正文:SpringBoot生命周期事件——BAT的乌托邦 正文 本文将以 SpringApplication的启动流程…

    Java 2023年5月30日
    097
  • 五、JDK的安装与配置

    一、JDK下载与安装 1.1、下载JDK安装包 博主在这里给大家准备了一个64位操作系统的jdk1.8以便大家下载(使用的是迅雷)点击此处下载提取码:dfbt 如果其他小伙伴的电脑…

    Java 2023年6月5日
    082
  • Kubernetes-Namespace

    1. 简介 Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群。 这些虚拟集群被称为 namespace。 在一些文档里 namespace也称为 &#x…

    Java 2023年6月7日
    074
  • 设计模式 10 装饰器模式

    装饰器模式(Decorator Pattern)属于 结构型模式 装饰,顾名思义,就是在原有基础上增添东西以显示更好的效果。 生活中非常多这样的例子, 衣服饰品、 珠宝首饰、 房子…

    Java 2023年6月6日
    070
  • AQS 源码分析

    一、AQS 简介 AQS,就是 AbstractQueuedSynchronizer,在同步组件的实现中,AQS是核心部分,同步组件的实现者通过使用AQS提供的模板方法实现同步组件…

    Java 2023年6月5日
    087
  • SpringBoot集成ffmpeg实现视频转码播放

    背景 之前构建过文件预览服务,对于视频部分前端播放组件限制只能为mp4格式,为了支持更多视频格式决定对方案进行升级,由于视频格式较多,针对每一种格式定制选择播放器不太现实,决定对视…

    Java 2023年6月15日
    073
  • 不落人后!简单好用的低代码开发,快速搭建智慧管理信息系统

    引言 伴随着社会的发展与时代的进步,管理与我们的生活密不可分,管理信息系统应用的范围十分广泛,体现在生活里的点点滴滴。管理信息系统不仅可以快速处理大量信息,还可以提高人们的工作效率…

    Java 2023年6月5日
    0133
  • 反射、注解、动态代理的理解

    反射 反射的核心就是拿到了.java编译后的.class文件。通过一系列的API,可以拿到该类中的成员:构造器、属性、方法等。 注解 注解,可以告诉编译器或者JVM做一些事情。比如…

    Java 2023年6月15日
    071
  • 动态代理

    动态代理。 讲到动态代理,就有对应的静态代理 静态代理的实现,方式1 继承目标类,生成一个子类。代理类和目标类是父子的关系。 然后在子类中进行逻辑的扩展,完成了静态代理。 方式2 …

    Java 2023年6月5日
    085
  • 《Effective Java 第三版》目录汇总

    经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习。时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正。 第三版全。下回再见,后会有期! Original:…

    Java 2023年5月29日
    093
  • Javaweb07-三层架构(BaseDao)

    1、BaseDao 持久层业务接口实现类的公共父类,定义了jdbc操作数据库的所有公共方法,方便子类继承; import java.io.InputStream; import j…

    Java 2023年6月15日
    084
  • Redis学习

    1.1 下载安装 环境Centos7.x https://redis.io/download 安装make(可选) yum -y install make 安装gcc(可选) yu…

    Java 2023年6月5日
    070
  • JAVA正则表达式:Pattern类与Matcher类详解(转)

    以下我们就分别来看看这两个类: 一、捕获组的概念 捕获组可以通过从左到右计算其开括号来编号,编号是从1 开始的。例如,在表达式 ((A)(B(C)))中,存在四个这样的组: 组零始…

    Java 2023年5月29日
    099
  • 解决Watt Toolkit(原steam++)的host代理443端口被占用的问题(电脑有虚拟机进!!)

    解决Watt Toolkit(原steam++) 的host代理443端口被占用的问题 写在前面 本来没法打算更改,但是公司为了上线微软商店还是将名字改了,所以我也修改一下。 一、…

    Java 2023年6月5日
    091
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球