Java的四大引用详解-冲击金三银四

强引用

    像“Object obj = new Object()”这类的引用均为强引用,当一个对象被强引用变量引用时,它处于可达状态,是不可能被垃圾回收器回收的,即使该对象永远不会被用到也不会被回收。

    当JVM出现内存不足时,JVM进行垃圾回收,对于强引用的对象,就算是出现了 OOM 也不会对该对象进行回收,打死都不收。因此强引用有时也是造成 Java 内存泄露的原因之一。如果将其引用赋值为null,一般认为是可以被垃圾回收掉的。(具体回收时间还要看使用的GC策略)

    示例代码:

public class StrongRefenenceDemo {public static void main(String[] args) {Object o1 = new Object();Object o2 = o1;o1 = null;System.gc();System.out.println(o1);  //nullSystem.out.println(o2);  //java.lang.Object@2503dbd3}
}

软引用

    软引用是一种相对强引用弱化了一些的引用,需要用java.lang.ref.SoftReference 类来实现,可以让对象豁免一些垃圾收集。

    软引用用来描述一些还有用,但并非必需的对象。

    对于只有软引用的对象:当系统内存充足时它不会被回收,当系统内存不足时它才会被回收。

//VM options: -Xms5m -Xmx5m
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);System.out.println(s1.get());o1 = null;System.gc();System.out.println(o1);System.out.println(s1.get());}/*** JVM配置`-Xms5m -Xmx5m` ,然后故意new一个一个大对象,使内存不足产生 OOM,看软引用回收情况*/private static void softRefMemoryNotEnough() {Object o1 = new Object();SoftReference<Object> s1 = new SoftReference<Object>(o1);System.out.println(o1);System.out.println(s1.get());o1 = null;byte[] bytes = new byte[10 * 1024 * 1024];System.out.println(o1);System.out.println(s1.get());}
}

输出结果:

--------------------------------------输出结果-------------------------------------------------
java.lang.Object@2503dbd3
java.lang.Object@2503dbd3
null
java.lang.Object@2503dbd3
------内存不够用的情况------
java.lang.Object@4b67cf4d
java.lang.Object@4b67cf4d
java.lang.OutOfMemoryError: Java heap space
at reference.SoftRefenenceDemo.softRefMemoryNotEnough(SoftRefenenceDemo.java:42)
at reference.SoftRefenenceDemo.main(SoftRefenenceDemo.java:15)
null
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);System.out.println(w1.get());o1 = null;System.gc();System.out.println(o1);//均被回收System.out.println(w1.get());//均被回收}
}

关于WeakHashMap示例代码

public class WeakHashDemo {public static void main(String[] args) throws InterruptedException  {myHashMap();System.out.println("-----------------------------------------------");myWeakHashMap();}public static void myHashMap() {HashMap<String, String> map = new HashMap<String, String>();String key = new String("k1");String value = "v1";map.put(key, value);System.out.println(map);key = null;System.gc();System.out.println(map);}public static void myWeakHashMap() throws InterruptedException {WeakHashMap<String, String> map = new WeakHashMap<String,  String>();// String key = "weak";// 刚开始写成了上边的代码// 思考一下,写成上边那样会怎么样?那可不是引用了String key = new String("weak");String value = "map";map.put(key, value);System.out.println(map);// 去掉强引用key = null;System.gc();Thread.sleep(1000);System.out.println(map);}
}
----------------------------------输出结果--------------------------------------------
{k1=v1}
{k1=v1}
-----------------------------------------------
{weak=map}
{}

 

虚引用

    虚引用也称为“幽灵引用”或者“幻影引用”,它是最弱的一种引用关系。虚引用需要java.lang.ref.PhantomReference 来实现。

    虚引用需要java.lang.ref.PhantomReference 来实现。

    如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收,它不能单独使用也不能通过它访问对象,虚引用必须和引用队列(RefenenceQueue)联合使用。

    虚引用的主要作用是跟踪对象垃圾回收的状态。仅仅是提供了一种确保对象被 finalize 以后,做某些事情的机制。

    PhantomReference 的 get 方法总是返回 null,因此无法访问对应的引用对象。其意义在于说明一个对象已经进入 finalization 阶段,可以被 GC 回收,用来实现比 finalization 机制更灵活的回收操作。

    设置虚引用的唯一目的,就是在这个对象被回收器回收的时候收到一个系统通知或者后续添加进一步的处理。

 

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);System.out.println(referenceQueue.poll());System.out.println(phantomReference.get());o1 = null;System.gc();Thread.sleep(3000);System.out.println(o1);System.out.println(referenceQueue.poll()); //引用队列中System.out.println(phantomReference.get());}}
-------------------------------------------------------------------------------------------------------
java.lang.Object@4554617c
null
null
null
java.lang.ref.PhantomReference@74a14482
null

引用队列

    ReferenceQueue 是用来配合引用工作的,没有ReferenceQueue 一样可以运行。

    SoftReference、WeakReference、PhantomReference 都有一个可以传递 ReferenceQueue 的构造器。

    创建引用的时候,可以指定关联的队列,当 GC 释放对象内存的时候,会将引用加入到引用队列。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动,这相当于是一种通知机制。

图片

Reference的四种状态:

  • Active:新创建的引用实例处于Active状态,但当GC检测到该实例引用的实际对象的可达性发生某些改变(实际对象处于 GC roots 不可达)后,它的状态将变化为Pending或者Inactive。如果 Reference 注册了ReferenceQueue,则会切换为Pending,并且Reference会加入pending-Reference链表中,如果没有注册ReferenceQueue,会切换为Inactive。

  • Pending:当引用实例被放置在pending-Reference 链表中时,它处于Pending状态。此时,该实例在等待一个叫Reference-handler的线程将此实例进行enqueue操作。如果某个引用实例没有注册在一个引用队列中,该实例将永远不会进入Pending状态。

  • Enqueued:在ReferenceQueue队列中的Reference的状态,如果Reference从队列中移除,会进入Inactive状态。

  • Inactive:一旦某个引用实例处于Inactive状态,它的状态将不再会发生改变,同时说明该引用实例所指向的实际对象一定会被GC所回收。

图片

​想要了解更多技术文章请关注公众号“职谷智享”,每天关注的前50名小伙伴可领取200+互联网相关技术书籍。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/716699.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

继承-重写

Phone基类&#xff1a; package ven;public class Phone {public Phone(){}public void call(String name){System.out.println("给"name"打电话");} } AIPhone子类&#xff1a; package ven;public class AIPhone extends Phone{Override //重载注解&am…

mTLS: openssl创建CA证书

证书可以通过openssl或者keytool创建&#xff0c;在本篇文章中&#xff0c;只介绍openssl。 openssl 生成证书 申请操作流程 生成ca证书私钥, 文件名&#xff1a;ca.key生成ca证书&#xff0c;文件名&#xff1a;ca.crt生成Server/Client 证书私钥&#xff0c;文件名&#x…

设计模式(十三)抽象工厂模式

请直接看原文:设计模式&#xff08;十三&#xff09;抽象工厂模式_抽象工厂模式告诉我们,要针对接口而不是实现进行设计。( )-CSDN博客 -------------------------------------------------------------------------------------------------------------------------------- …

系统架构设计文档模版

XX 系统架构设计方案 修订记录 日期 版本号 修订说明 修订人 审核人 1、概述... 5 1.1&#xff0e;业务背景... 5 1.2&#xff0e;系统总体描述... 5 1.3&#xff0e;系统边界图... 5 1.4&#xff0e;名词和缩略语... 5 1.…

live555源码学习(1)

1 基础组件 live项目主要包含了四个基础库、程序入口类&#xff08;mediaServer&#xff09;和测试程序&#xff08;testProgs&#xff09;。四个基础库是UsageEnvironment、BasicUsageEnvironment、groupsock和liveMedia UsageEnvironment 抽象了两个类UsageEnvironment和T…

力扣hot5---双指针

题目&#xff1a; 解决方案&#xff1a;双指针 指针 i 指向最左侧&#xff0c;指针 j 指向最右侧。此时在宽度上达到了最大值&#xff0c;那么哪个柱子更矮&#xff0c;哪个柱子向内部移动&#xff0c;知道 i 与 j 相遇。为什么呢&#xff1f; 如果哪个哪个柱子更矮&#xff0c…

代码随想录算法训练营第四十一天|198.打家劫舍,213.打家劫舍II,337.打家劫舍III

系列文章目录 代码随想录算法训练营第一天|数组理论基础&#xff0c;704. 二分查找&#xff0c;27. 移除元素 代码随想录算法训练营第二天|977.有序数组的平方 &#xff0c;209.长度最小的子数组 &#xff0c;59.螺旋矩阵II 代码随想录算法训练营第三天|链表理论基础&#xff…

Node.js基础---模块化

基本概念 模块化 模块化是指解决一个复杂问题时&#xff0c;自上向下逐层把系统划分成若干模块的过程&#xff0c;对于整个系统来说&#xff0c;模块是可组合&#xff0c;分解和更换的单元 遵守固定规则&#xff0c;把大文件拆分成独立并互相依赖的多个小模块 好处&#xff1a…

【计算机毕业设计】208基于SSM的在线教育网站

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

OLLAMA:如何像专业人士一样运行本地语言模型

原文 https://cheatsheet.md/llm-leaderboard/ollama.en简介&#xff1a;揭示 OLLAMA 对本地语言模型的强大功能 您是否曾经发现自己陷入了基于云的语言模型网络中&#xff0c;渴望获得更本地化、更具成本效益的解决方案&#xff1f;好吧&#xff0c;您的搜索到此结束。欢迎来…

逆向案例四、进阶,爬取精灵数据咨询前五十页数据

python代码示例: import csv import execjs import requests f open(精灵数据.csv,w,encodingutf-8,newline) csv_writer csv.DictWriter(f,fieldnames[标题,发布时间,新闻来源,详情页链接,转自,点击量,新闻作者,发布时间小时,]) csv_writer.writeheader() data [] for pa…

【Ansys Fluent Web 】全新用户界面支持访问大规模多GPU CFD仿真

基于Web的技术将释放云计算的强大功能&#xff0c;加速CFD仿真&#xff0c;从而减少对硬件资源的依赖。 主要亮点 ✔ 使用Ansys Fluent Web用户界面™&#xff08;UI&#xff09;&#xff0c;用户可通过任何设备与云端运行的仿真进行远程交互 ✔ 该界面通过利用多GPU和云计算功…

理解python3中的回调函数

百度百科说&#xff1a;回调函数就是一个通过函数指针调用的函数。如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另一个函数&#xff0c;当这个指针被用来调用其所指向的函数时&#xff0c;我们就说这是回调函数。回调函数不是由该函数的实现方直接调用&#…

Sqli-labs靶场第13关详解[Sqli-labs-less-13]

Sqli-labs-Less-13 #手工注入 post传参了 根据题目看&#xff0c;像一个登录页面&#xff0c;尝试使用布尔型盲注测试能否登录网站 1. Username输入a 测试是否会有报错&#xff0c;burp抓包 报错&#xff1a;syntax to use near a) and password() LIMIT 0,1 at line 1 分…

[python] `json.dumps()` TypeError: Object of type set is not JSON serializable

在Python中&#xff0c;当你尝试将一个集合&#xff08;set&#xff09;类型的对象转换为JSON格式时&#xff0c;可能会遇到“TypeError: Object of type set is not JSON serializable”的错误。这是因为标准的JSON格式不支持Python中的集合类型&#xff0c;JSON格式支持的数据…

【04】C语言括号匹配问题

欢迎来到土土的博客~&#x1f973;&#x1f973;&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#xff1a;大耳朵土土垚的博客 &#x1f4a5; 所属专栏&#xff1a;C语言系列函数实现 题目描述&#xff1a; 给定一个只包括 ‘(’&#xff0c;‘)’&#xf…

加密隧道技术

在现在的互联网上传输数据&#xff0c;首要考虑的就是安全。这关乎到你的隐私&#xff0c;个人信息&#xff0c;财产安全等等重大问题。如果你的程序本身传输的信息没有加密&#xff0c;也可以通过其他辅助方式让你的通信加密。一些工具的就是为了解决这样的场景的&#xff0c;…

之前续写抖音开发者接入字节小游戏的缓存一下,现在说一下在 Windows 或者 Mac 如何用终端更换路径?

window: 比方说你的 window 目录下是这个路径: 第一:E:\project\Q1\trunk\client\src,然后你想切换到下一个路径的话,你可以这样子操作: 第二:E:\project\Q1\trunk\client\src> cd .\usersetting 然后回车,这里不会计较大小写 第三:你就可以在这个目录下执行你的脚本:E:…

学习大数据,所必需的java基础(7)

文章目录 File类File 的静态成员File的构造方法File的获取方法相对路径和绝对路径File的创建方法File类中的删除方法File的遍历方法 字节流IO流介绍以及输入输出以及流向的介绍IO流的流向IO流分类IO流分类 OutputStream中的子类FileOutoutStream的介绍以及方法的简单介绍InputS…

服务器中如何检查端口是否开放

有多种方法可以检测服务器端口是否开放。以下是一些常用的方法&#xff1a; 1. Telnet 命令&#xff1a; 使用 Telnet 命令来测试端口的可达性。在命令提示符或终端中执行以下命令&#xff1a; telnet your_server_ip your_port_number 如果连接成功&#xff0c;表示端口是…