【Java】垃圾回收学习笔记(一):判定对象的存活或死亡?Root Search 根可达算法

文章目录

  • 1. 引用计数法
      • 优点
      • 缺点
  • 2. 可达性分析 Root Search
    • 2.1 那些对象是GC Roots
    • 2.2 引用的分类
  • 3. 回收方法区
  • Reference

最近上班地铁上偶尔看看书,周末有空理一下,做个笔记。
下面说说GC过程中如何判断对象是否存活。

1. 引用计数法

用于微软COM(Component Object Model)计数、Python语言等,进行内存管理。原理就是在对象中添加一个引用计数器:

  • 每当有地方引用他时,计数器加一;
  • 引用失效时,计数器减一;
  • 计数器为零时,对象就是不可能再被使用的。

优点

原理简单,判断效率高

缺点

单纯的引用计数很难解决对象间的相互循环引用问题,需要考虑很多额外情况

另外,Java虚拟机并不用引用计数来判断对象是否存活

2. 可达性分析 Root Search

Java、C#等主流商用程序语言凑采用可达性分析(Reachability Analysis)算法判定对象是否存活:

  1. 枚举一系列对象作为GC Roots
  2. 从GC Roots出发,搜索引用链,某个对象不可达时,则该对象判定为不可能再被使用(死亡)

在这里插入图片描述

2.1 那些对象是GC Roots

Java中,可作为GC Roots的对象包括:

  • 在虚拟机栈(栈帧中的本地变量表)中引用的对象,也就各个线程调用的对象;
  • 方法区中,类静态属性引用的对象;
  • 方法区中,常量引用的对象,比如字符串常量池中的引用;
  • 本地方法栈(Native方法)引用的对象;
  • JVM内部的引用,比如
    • 基本数据类型(float、double、int、long、byte、char、boolean)对应的Class对象
    • 常驻的异常对象(NullPointException、OutOfMemoryError)
    • 类加载器(BootstrapClassLoader、ExtensionClassLoader、AppClassLoaderfab)等等;
  • synchronized关键字持有的锁对象(一般是static对象,或者是当前类的Class对象);
  • 反应JVM内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等

在分代回收和局部回收过程中,可能会有临时对象加入GC Roots集合,来解决跨代引用等问题。

2.2 引用的分类

JDK1.2之后,Java扩充了引用的定义,不同引用在GC时的行为有所差异:

  • 强引用(Strongly Reference):在代码中通过Object o = new Object() 形势产生的引用关系。只要强引用存在,GC就不会回收被引用对象(哪怕OOM)。

  • 软引用(Soft Reference):通过SoftReference 类实现的引用。系统内存发生内存溢出前,会将软引用对象列入回收范围进行回收,如果回收后还没有足够内存,就抛出OOM。

  • 弱引用(Weak Reference):通过WeakReference 类实现的引用。无论内存是否足够,弱引用对象都会被GC。

  • 虚引用(Phantom Reference):通过PhantomReference 类实现的引用。虚引用无法对对象实际的生存时间造成影响,也不能通过虚引用来获得对象实例。虚引用的作用就是追踪对象的GC信息,在被回收时加入到关联的引用队列,可以得到一个通知或做些其他事。

    import java.lang.ref.PhantomReference;
    import java.lang.ref.ReferenceQueue;
    public class PhantomReferenceExample {public static void main(String[] args) {Object obj = new Object();ReferenceQueue<Object> queue = new ReferenceQueue<>();PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue);// 执行对象的清理操作Thread cleanupThread = new Thread(() -> {try {while (true) {PhantomReference<?> reference = (PhantomReference<?>) queue.remove();// 执行清理操作,比如释放资源System.out.println("Cleanup: " + reference);}} catch (InterruptedException e) {e.printStackTrace();}});cleanupThread.setDaemon(true);cleanupThread.start();obj = null; // 取消强引用System.gc(); // 手动触发垃圾回收// 在这里可以进行一些其他操作}
    }
    

    根可达算法中判定为不可达的对象,可以在finallize()方法中重新增加引用关联来复活(只能复活一次,try…finally也行)

3. 回收方法区

《Java虚拟机规范》:可以不要求虚拟机在方法区中实现垃圾回收(比如JDK11 的ZGC收集器就不支持类卸载)。因为方法区回收的性价比通常较低。

方法区允许(不是必须)回收的对象一般是废弃的常量不再使用的类

  • 废弃的常量:类似堆中的对象,即没引用的常量。比如常量池中有个字符串对象,值为“java”,其回收条件为
    • 没用其他任何对象引用“java”常量;
    • 虚拟机中没有“java”字面量的引用。
  • 不再被使用的类需要同时满足三个条件才会允许(不是必须)被回收(即类卸载):
    • 该类的所有实例都已经被回收(堆中不存在该类及其子类的实例);
    • 加载该类的类加载器已经被回收;
    • 该类对应的Class对象也没被引用(即不能通过反射访问该类的method跟filed)。

Hotspot虚拟机提供了-Xnoclassgc参数进行类卸载控制,还有一系列参数查看类可查看类加载和类卸载信息。

在动态代理大量使用的场景(大量使用反射、CGLib等),或者需频繁自定义类加载器等场景中,通常需要JVM具备类卸载能力,以保证生成的代理类对象不会对方法区造成过大压力。

Reference

《深入理解java虚拟机:JVM高级特性与最佳时间(第3版)》 周志明
ps:虚引用的例子是也是网上找的,但原文找不到了

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

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

相关文章

文心一言 VS 讯飞星火 VS chatgpt (297)-- 算法导论22.1 1题

一、给定有向图的邻接链表&#xff0c;需要多长时间才能计算出每个结点的出度(发出的边的条数)&#xff1f;多长时间才能计算出每个结点的入度(进入的边的条数)&#xff1f;如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 计算出度 对于有向图的邻接链表表示&a…

redolog的刷盘策略

mysql通过innodb_flush_log_at_trx_commit配置来控制redo log的写盘时机。 0&#xff1a;延迟写。提交事务时不会将redo log写入os buffer&#xff0c;而是每隔1秒将redo log写入os buffer并调用fsync()刷入磁盘。系统崩溃会丢失一秒钟的数据。 1&#xff1a;实时写&#xff0c…

基于OpenCv的快速图片颜色交换,轻松实现图片背景更换

图片颜色更换 图片颜色转换 当我们有2张图片,很喜欢第一张图片的颜色,第2张图片的前景照片,很多时候我们需要PS进行图片的颜色转换,这当然需要我们有强大的PS功底,当然小编这里不是介绍PS的,我们使用代码完全可以代替PS 进行图片的颜色转换 图片颜色转换步骤: 步骤…

MySQL高级----详细介绍MySQL中的锁

概述 锁是计算机协调多个进程或线程并发访问某一资源的机制&#xff0c;为了解决数据访问的一致性和有效性问题。在数据库中&#xff0c;除传统的计算资源(CPU、RAN、I/O&#xff09;的争用以外&#xff0c;数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、…

U盘非安全退出后的格式化危机与高效恢复策略

在数字化时代&#xff0c;U盘作为数据存储与传输的重要工具&#xff0c;其数据安全备受关注。然而&#xff0c;一个常见的操作失误——U盘没有安全退出便直接拔出&#xff0c;随后再插入时却遭遇“需要格式化”的提示&#xff0c;这不仅让用户措手不及&#xff0c;更可能意味着…

vs code格式化

目录 vs code格式化 函数参数不换行 禁止 pylance 插件自动添加 import vs code格式化 函数参数不换行 def generate_canvas_box(self,corners,idxs,thickness2,data_idxNone,debug False): 方法四&#xff1a;使用 VS Code 的自定义格式化设置 打开 VS Code 设置&#xff…

【软考】SSH

目录 1. 说明2.特点2.1 安全性2.2 灵活性2.3 功能性2.3 易用性 3. 工作原理 1. 说明 1.Secure Shell。2.是一种加密的网络协议&#xff0c;用于安全地访问远程计算机或服务器。3.SSH提供了加密的通道&#xff0c;使得用户可以通过这个通道在本地计算机和远程计算机之间安全地传…

vivado DCI_CASCADE、DELAY_BYPASS

DCI_CASCADE DCI_CASCADE定义了一组高性能&#xff08;HP&#xff09;之间的主从关系 I/O银行。数字控制阻抗&#xff08;DCI&#xff09;参考电压从 主I/O库到从I/O库。 DCI_CASCADE指定哪些相邻库使用DCI级联功能&#xff0c;从而共享 具有主组的参考电阻器。如果同一I/O组列…

【无标题】AMAZINGIC晶焱科技:汽车电子 EOS 测试与防护

因牵涉到人身安全且需确保车辆正常行驶&#xff0c;车用产品的测试条件会比一般消费性产品还要严苛许多&#xff0c;大部分采用的EMC测试法规都是车载专用标准&#xff0c;因此汽车电子的验证几乎是独立于其他领域的。本文将集成晶焱科技深耕车用市场的经验&#xff0c;探讨汽车…

Spring Boot应用使用GraalVM本地编译相关配置

1. 介绍 Java应用程序可以通过Graalvm Native Image提前编译生成与本地机器相关的可执行文件。与在JVM执行java程序相比&#xff0c;Native Image占用内存更小和启动速度更快。 从spring boot3开始支持GraalVM Native Image&#xff0c;因此要使用此特性&#xff0c;需要把sp…

count(1)和count(*)和count(field)的区别

1.COUNT(*) 计算所有行的数量&#xff0c;包括那些含有 NULL 值的行。 它是最全面的计数方法&#xff0c;因为它不需要访问任何具体的列数据&#xff0c;只是简单地计算行数。 在大多数情况下&#xff0c;COUNT(*) 是最快的&#xff0c;尤其是在使用索引的情况下&#xff0c;…

大气热力学(3)——干空气与湿空气

本篇文章源自我在 2021 年暑假自学大气物理相关知识时手写的笔记&#xff0c;现转化为电子版本以作存档。相较于手写笔记&#xff0c;电子版的部分内容有补充和修改。笔记内容大部分为公式的推导过程。 文章目录 3.0 本文所用符号一览3.1 干空气与湿空气的概念3.2 干空气的状态…

kubeadm快速部署k8s集群

文章目录 Kubernetes简介1、k8s集群环境2、linux实验环境初始化【所有节点】3、安装docker容器引擎【所有节点】4、安装cri-dockerd【所有节点】5、安装 kubeadm、kubelet、kubectl【所有节点】6、部署 k8s master 节点【master节点】7、加入k8s Node 节点【node节点】8、部署容…

【JavaWeb程序设计】JSP访问数据库

目录 一、安装Mysql&#xff0c;设置好数据库的账户和密码 二、JSP访问数据库的步骤 ①加载数据库驱动程序&#xff1b; ②建立连接对象&#xff1b; ③创建语句对象&#xff1b; ④获得结果集&#xff1b; ⑤关闭有关连接对象。 三、实现个人信息的查询和展示 1、新增…

Week 5-杨帆-学习总结

目录 46 语义分割和数据集语义分割与其他技术的区别Pascal VOC2012 语义分割数据集数据预处理自定义语义分割数据集类数据加载与批量处理遇到的问题&解决办法 47 转置卷积转置卷积的基本概念转置卷积的基本操作填充和步幅在转置卷积中的作用多通道的转置卷积与矩阵变换的联…

2024年生成式人工智能(AIGC)进化速度太快了,如何帮助我们提升效率呢

在软件工程领域里&#xff0c;生成式人工智能&#xff08;AIGC&#xff09;正悄然重塑着程序员的日常作业模式。从源码的自动编写&#xff0c;到瑕疵的敏锐捕捉&#xff0c;再到测试流程的自主执行&#xff0c;AI驱动的工具已然晋升为编程人员不可或缺的智囊团。尽管如此&#…

Java String操作工具类:StrUtil

在日常的Java开发中&#xff0c;字符串&#xff08;String&#xff09;是最常用的数据类型之一。无论是数据处理、文本分析还是界面展示&#xff0c;都离不开对字符串的精细操作。然而&#xff0c;尽管Java标准库提供了丰富的字符串处理方法&#xff0c;但在实际项目中&#xf…

缓存-缓存使用2

1.缓存击穿、穿透、雪崩 1.缓存穿透 指查询一个一定不存在的数据&#xff0c;由于缓存是不命中&#xff0c;将去查询数据库&#xff0c;但是数据库也无此纪录&#xff0c;我们没有将这次查询的null写入缓存&#xff0c;这将导致这个不存在的数据每次请求都要到存储层去查询&a…

java信号量(Semaphore)

Java中的信号量&#xff08;Semaphore&#xff09;是一种用于控制多个线程对共享资源的访问的同步工具。它可以用来限制可以同时访问某些资源的线程数量。Semaphore 提供了一个计数器来管理许可证的获取和释放&#xff0c;每个许可证代表对资源的一次访问权限。 import java…

如何构建一个可伸缩的微服务架构?

如何构建一个可伸缩的微服务架构&#xff1f; 大家好&#xff0c;我是微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 微服务架构是一种将应用程序设计为一组小型服务的架构风格&#xff0c;每个服务运行在自己的进程中&am…