JVM---对象是否存活及被引用的状态

1.如何判断对象是否存活

1.1 引用计数算法

        概念:在对象头部增加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的。

        优点:速度快,高效

        缺点: 假如此时A引用B,B引用A那么,计数永远不为0,那么永远无法回收他们

1.2 可达性分析算法:

        概念:通过一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”(Reference Chain),如果某个对象到GC Roots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。

       总结概念: 也就是找到是否连接根节点,此时如果A引用B,B引用A就不会发生,循环回收不掉的问题,因为他们找不到连接的根节点,也是当前主流的判断对象是否存活的算法

        注意:即使在可达性分析算法中判定为不可达的对象,也不是“非死不可”的,这时候它们暂时还处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历两次标记过程:如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记,随后进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。

2.再谈引用

        无论是通过引用计数算法判断对象的引用数量,还是通过可达性分析算法判断对象是否引用链可 达,判定对象是否存活都和“ 引用 离不开关系。
        在JDK 1.2 版之前, Java 里面的引用是很传统的定义: 如果reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称该 reference 数据是代表 某块内存、某个对象的引用。这种定义并没有什么不对,只是现在看来有些过于狭隘了,一个对象在 这种定义下只有“ 被引用 或者 未被引用 两种状态,对于描述一些 食之无味,弃之可惜 的对象就显 得无能为力。
        譬如我们希望能描述一类对象:当内存空间还足够时,能保留在内存之中,如果内存空
间在进行垃圾收集后仍然非常紧张,那就可以抛弃这些对象 —— 很多系统的缓存功能都符合这样的应用场景。
        所以在JDK 1.2版之后,Java对引用的概念进行了扩充,引入了四种引用

3.四种引用

2.1  强引用

        是最传统的“引用”的定义,是指在程序代码之中普遍存在的引用赋值,即类似“Object obj=new Object()”这种引用关系。无论任何情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象。

2.2 软引用

        是用来描述一些还有用,但非必须的对象。只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。在JDK 1.2版之后提供了SoftReference类来实现软引用。

2.3 弱引用

        也是用来描述那些非必须对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK 1.2版之后提供了WeakReference类来实现弱引用。

2.4 虚引用

        也称为“幽灵引用”或者“幻影引用”,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。在JDK 1.2版之后提供了PhantomReference类来实现虚引用。

3. 软引用的进一步了解

3.1 软引用的使用场景

         软引用主要用于实现内存敏感的高速缓存。当系统内存充足时,软引用的对象可以长时间驻留在内存中,供程序快速访问;当系统内存不足时,这些对象可以被垃圾回收器回收,从而避免内存溢出错误。这种机制非常适合用于缓存系统,如图片缓存、页面缓存等。

3.2 为什么用到了软引用

  1. 内存压力下的灵活应对:软引用允许JVM在内存紧张时自动回收对象,从而避免了程序因为内存不足而崩溃的风险。

  2. 提高性能:通过保留软引用对象,在内存充足时可以直接访问这些对象,减少了重新加载或重新计算这些对象所需的时间和资源。

  3. 资源管理的灵活性:开发者可以通过软引用来控制缓存的大小和生命周期,而不是完全依赖于JVM的垃圾回收机制。

3.3 软引用的使用(小例子)

import java.lang.ref.SoftReference;  public class SoftReferenceExample {  public static void main(String[] args) {  // 假设这是我们需要缓存的数据  Object data = new Object();  // 创建一个软引用指向这个数据  SoftReference<Object> softRef = new SoftReference<>(data);  // 使用softRef.get()来获取软引用指向的对象  Object cachedData = softRef.get();  // 模拟内存紧张的情况(实际上在简单示例中无法直接模拟)  // 在实际环境中,当JVM进行垃圾回收时,如果内存不足,可能会回收softRef指向的对象  // 再次尝试获取对象,如果对象已被回收,则返回null  cachedData = softRef.get();  if (cachedData != null) {  // 对象仍然存在,可以继续使用  } else {  // 对象已被回收,需要重新加载或重新计算  }  }  
}

注意:由于垃圾回收的时机和过程是由JVM的垃圾回收器控制的,因此我们不能精确地预测软引用对象何时会被回收。在实际应用中,开发者需要根据应用的内存需求和性能要求来合理使用软引用。

4. 弱引用的进一步了解

4.1 使用场景

  1. 缓存系统
    • 在一些缓存系统中,特别是当缓存的数据量很大且不是必需时,可以使用弱引用来引用这些数据。这样,当JVM内存不足时,这些数据可以被自动回收,从而避免内存溢出。
    • 例如,WeakHashMap就是基于弱引用实现的,它允许键值对中的键是弱引用的。这意味着,如果某个键除了被WeakHashMap所引用外,没有其他强引用指向它,那么这个键以及它所对应的值都可能被垃圾回收器回收。
  2. 生命周期较短的临时对象
    • 对于那些生命周期较短,且对内存敏感的临时对象,可以使用弱引用来引用它们。这样,一旦这些对象不再被其他强引用所指向,它们就可以被垃圾回收器及时回收。

4.2 为什么用到了弱引用

  1. 内存管理的灵活性
    • 弱引用提供了一种比软引用更加灵活的内存管理方式。通过弱引用,开发者可以更加精确地控制对象的生命周期,避免内存泄漏,同时也能够确保在内存不足时能够自动回收非必需的对象。
  2. 减少内存泄漏的风险
    • 在一些复杂的应用程序中,由于对象之间的引用关系错综复杂,很容易出现内存泄漏的情况。通过使用弱引用,可以减少因为对象之间的强引用关系而导致的内存泄漏风险。
  3. 提升性能
    • 在一些性能敏感的应用程序中,及时回收不再使用的对象可以释放更多的内存空间,从而提升应用程序的性能。弱引用通过自动回收非必需的对象,有助于减少内存占用,提升性能。

4.3 弱引用的使用(小例子)

import java.lang.ref.WeakReference;  public class WeakReferenceExample {  public static void main(String[] args) {  // 创建一个强引用对象  Object strongRef = new Object();  // 创建一个弱引用对象,指向强引用对象  WeakReference<Object> weakRef = new WeakReference<>(strongRef);  // 验证弱引用是否有效  System.out.println(weakRef.get()); // 输出对象地址  // 将强引用置为null,模拟对象不再被强引用  strongRef = null;  // 触发垃圾回收(注意:实际环境中,垃圾回收的时机是不确定的)  System.gc();  // 再次验证弱引用是否有效  // 由于强引用已被置为null,且没有其他强引用指向该对象,因此该对象可能会被垃圾回收  // 此时,weakRef.get()可能返回null  System.out.println(weakRef.get()); // 可能输出null  }  
}

同样和弱引用相同:由于垃圾回收的时机和过程是由JVM的垃圾回收器控制的,因此我们不能精确地预测弱引用对象何时会被回收。在实际应用中,开发者需要根据应用的内存需求和性能要求来合理使用弱引用。

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

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

相关文章

vue2迁移到vue3注意点

vue2迁移到vue3注意点 1、插槽的修改 使用 #default &#xff0c; 以及加上template 模板 2、 类型的定义&#xff0c;以及路由&#xff0c;vue相关资源&#xff08;ref, reactive,watch&#xff09;的引入等 3、类装饰器 1&#xff09;vue-class-component是vue官方库,作…

ubuntu搭建harbor私仓

1、环境准备 链接: https://pan.baidu.com/s/1q4XBWPd8WdyEn4l253mpUw 提取码: 7ekx --来自百度网盘超级会员v2的分享 准备一台Ubuntu 机器:192.168.124.165 将上面两个文件考入Ubuntu上面 2、安装harbor 安装Docker Harbor仓库以容器方式运行,需要先安装好docker,参考:…

详解python基本语法

文章目录 数据变量数据结构 循环-判断-用户输入判断用户输入循环 函数参数返回值将函数存储在模块中 文件和异常读取文件异常操作Json文件 类对象创建类使用类类的继承导入外部类 测试测试函数创建测试 Python 是一种广泛使用的高级编程语言&#xff0c;以其清晰的语法和代码可…

which 命令在Linux中是一个快速查找可执行文件位置的工具

文章目录 0、概念1、which --help2、which命令解释 0、概念 which命令用于查找命令的可执行文件的路径which 命令在 Linux 中用于查找可执行命令的完整路径。当你在 shell 中输入一个命令时&#xff0c;shell 会在环境变量 $PATH 定义的目录列表中查找这个命令。which 命令可以…

React基础学习-Day06

React基础学习-Day06 zustand基本使用方式 1.基础使用 基本使用 zustand 的步骤包括创建状态存储和在组件中使用这些状态和更新函数。以下是一个基础的示例&#xff0c;演示如何使用 zustand 来管理一个简单的计数器状态。 安装 首先&#xff0c;确保你的项目中已经安装了…

socket编程(2) -- TCP通信

TCP通信 2. 使用 Socket 进行TCP通信2.1 socket相关函数介绍socket()bind()listen()accept()connect()2.2 TCP协议 C/S 模型基础通信代码 最后 2. 使用 Socket 进行TCP通信 Socket通信流程图如下&#xff1a; 这里服务器段listen是监听socket套接字的监听文件描述符。如果客户…

Redis--布隆过滤器

解决缓存穿透是构建高效缓存系统中的关键问题之一。缓存穿透指的是恶意或者非法请求经过缓存层直接访问数据库或者后端服务&#xff0c;导致系统资源浪费和性能下降的情况。为了有效应对缓存穿透问题&#xff0c;以下是几种常见的解决方法&#xff1a; 1. 布隆过滤器预检查 布…

运维-Docker-黑马

运维-Docker-黑马 编辑时间&#xff1a;2024/7/15 来源&#xff1a;黑马程序员 docker&#xff1a;快速构建&#xff0c;运行&#xff0c;管理应用的工具 Docker安装 部署mysql 命令解读

[Cesium for Supermap] 加载3dTiles,点击获取属性

代码&#xff1a; // 设为椭球var obj [6378137.0, 6378137.0, 6356752.3142451793];Cesium.Ellipsoid.WGS84 Object.freeze(new Cesium.Ellipsoid(obj[0], obj[1], obj[2]));var viewer new Cesium.Viewer(cesiumContainer);var scene viewer.scenescene.lightSource.ambi…

Oracle TDE(Transparent Data Encryption) 常见问题解答 - 官网

此FAQ来源于官网链接。此为新版&#xff0c;老版的博客参见Oracle TDE(Transparent Data Encryption) 常见问题解答。 通用问题 透明数据加密 (TDE) 提供什么功能&#xff1f; TDE 以透明方式加密 Oracle 数据库中的静态数据。它可以阻止操作系统未经授权尝试访问存储在文件…

彻底改变时尚:使用 GAN 实现 AI 的未来

彻底改变时尚&#xff1a;使用 GAN 实现 AI 的未来 一、介绍 想象一下&#xff0c;在这个世界里&#xff0c;时装设计师永远不会用完新想法&#xff0c;我们穿的每一件衣服都是一件艺术品。听起来很有趣&#xff0c;对吧&#xff1f;好吧&#xff0c;我们可以在通用对抗网络 &a…

鸿蒙基本工程目录

工程级目录 AppScope 中存放应用全局所需要的资源文件。entry 是应用的主模块&#xff0c;存放 HarmonyOS 应用的代码、资源等。oh_modules 是工程的依赖包&#xff0c;存放工程依赖的源文件。build-profile.json5 是工程级配置信息&#xff0c;包括签名、产品配置等。hvigorf…

品牌产业出海指南如何搭建国际化架构的跨境电商平台?

在“品牌&产业出海指南 – 成功搭建跨境电商平台”系列中&#xff0c;我们将从电商分销系统、跨境平台商城/多商户商城系统和国际化架构三个方面对帮助您梳理不同平台模式的优缺点、应用场景、开发重点和运营建议。 在“品牌&产业出海指南 – 成功搭建跨境电商平台”系…

【漏洞复现】Rejetto HTTP文件服务器——远程命令执行(CVE-2024-23692)

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 Rejetto HTTP文件服务器是一个轻量级的HTTP服务器软件&#xff…

VBA学习(20):一批简单的Excel VBA编程问题解答

1.如何确定单元格区域内的行数和列数&#xff1f; 使用Range.Rows.Count和Range.Columns.Count属性。 2.Application.Columns指的是什么&#xff1f; 活动工作表中的列。 3.你的程序在列B位置插入一个新列&#xff0c;原来的列B会怎样&#xff1f; 它向右移动成为列C。 4.假…

vue项目1分钟实现自定义右键菜单,懒人的福音

高效实现需求&#xff0c;避免重复造轮子&#xff0c;今天给大家分享的是&#xff0c;如何在最短的时间内实现右键菜单&#xff0c;方法也很简单&#xff0c;一个插件就可以搞定&#xff0c;话不多说&#xff0c;上效果图&#xff1a; 1. 效果图&#xff1a; 2. 安装&#xff…

5. 基于Embedding实现超越elasticsearch高级搜索

Embedding介绍 Embedding是向量的意思&#xff0c;向量可以理解为平面坐标中的一个坐标点(x,y),在编程领域&#xff0c;一个二维向量就是一个大小为float类型的数组。也可以用三维坐标系中的向量表示一个空间中的点。在机器学习中&#xff0c;向量通常用于表示数据的特征。 向量…

SCI丨中三区

无线网络遥感图像和视频处理技术在xxxxx析基于智能物联网的xxxxx养老模式可持续发展基于心理行为大数据分类算法xxxxxx研究基于云计算xxxxx行为分析及客户感知体系的构建基于机器学习的xxxxx金钢时效行为研究 基于机器视觉的xxxxx检测系统研究 机器学习的电子显微镜xxxxx材料的…

探索Laravel的视图组件与插槽:构建动态且可复用的UI

探索Laravel的视图组件与插槽&#xff1a;构建动态且可复用的UI 引言 Laravel作为一个现代化的PHP框架&#xff0c;提供了许多强大的功能来帮助开发者构建高性能和可维护的Web应用。其中&#xff0c;视图组件&#xff08;View Components&#xff09;和插槽&#xff08;Slots…

【React Hooks原理 - forwardRef、useImperativeHandle】

概述 上文我们聊了useRef的使用和实现&#xff0c;主要两个用途&#xff1a;1、用于持久化保存 2、用于绑定dom。 但是有时候我们需要在父组件中访问子组件的dom或者属性/方法&#xff0c;而React中默认是不允许父组件直接访问子组件的dom的&#xff0c;这时候就可以通过forwa…