JVM工作原理与实战(二十三):堆的垃圾回收-引用计数法和可达性分析法

专栏导航

JVM工作原理与实战

RabbitMQ入门指南

从零开始了解大数据


目录

专栏导航

前言

一、判断堆上的对象是否可以回收

1.引用计数法

2.可达性分析算法

二、查看垃圾回收日志

总结


前言

JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了判断堆上的对象是否可以回收的方法(引用计数法、可达性分析法)、查看垃圾回收日志等内容。


一、判断堆上的对象是否可以回收

在垃圾回收过程中,首要任务是判断哪些对象可以安全地回收。常见的判断方法主要有两种:引用计数法可达性分析法

1.引用计数法

引用计数法是一种直观且简单的垃圾回收策略。每个对象都持有一个引用计数器,当一个对象被引用时,其计数器加1;当引用被解除时,计数器减1。当计数器归0时,对象即被认为是可以回收的。

引用计数法的优点在于其实现简单,对于某些特定场景(如C++中的智能指针)非常适用。然而,它也存在一些明显的缺点:

  • 每次引用或取消引用都需要更新计数器,这可能对系统性能产生影响。尤其是在对象引用频繁增减的情况下,这可能导致大量的更新操作,从而影响程序的运行效率。
  • 引用计数法无法处理循环引用的情况。例如,当对象A引用对象B,同时对象B也引用对象A时,即使这两个对象之间没有其他外部引用,它们的引用计数也不会归0,从而导致无法正常回收,造成内存泄漏。

2.可达性分析算法

相比之下,可达性分析算法更为复杂,但它能够解决循环引用问题。在可达性分析中,所有对象被分为两类:垃圾回收的根对象(GC Root)和普通对象。这些根对象通常是程序中可以直接访问的对象。算法通过追踪从根对象到目标对象的引用链,来判断一个对象是否可达。如果一个对象从任何根对象都无法达到,那么这个对象就被认为是不可达的,可以被安全地回收。

案例:

在图中,A对象引用了B对象,B对象又引用了C和D对象,从而形成了一个引用链。可达性分析算法的核心思想在于,如果一个对象无法从垃圾回收的根对象(GC Root)可达,那么这个对象就可以被安全地回收。反之,如果一个对象可以从某个GC Root对象可达,那么这个对象就被认为是活动的,不可被回收。

在Java中,就采用了可达性分析算法来判定对象是否可以回收。所有的根对象都存在于线程的栈中或者其他一些固定区域(例如JDK中的强引用、软引用、弱引用、虚引用)。如果一个对象被根对象直接或间接引用,那么这个对象就被认为是活动的、不可被回收的;反之,如果一个对象没有任何根对象引用它,那么这个对象就可以被垃圾回收。

可达性分析算法的主要优点是它可以处理复杂的引用关系和避免循环引用的问题。然而,它也有一些缺点:

  • 可达性分析算法需要追踪和记录所有的引用关系,这可能会增加内存和CPU的使用。
  • 如果一个程序在运行过程中改变了引用关系(例如在Java中的null指针异常),这可能会影响到垃圾回收的结果。
  • 对于一些动态生成的对象或者短生命周期的对象,可达性分析可能无法有效地判定其是否可以回收。

GC Root对象:

在垃圾回收过程中,GC Root对象是指垃圾回收的起始点。这些对象是可达的,并且通过引用关系可以访问到堆上的其他对象。常见的GC Root对象包括:

  • 线程Thread对象:每个线程在Java虚拟机中都有一个对应的Thread对象,这些对象引用线程栈帧中的方法参数、局部变量等,为垃圾回收提供了可达性路径。
  • 系统类加载器加载的java.lang.Class对象:系统类加载器加载的java.lang.Class对象,这些对象引用类中的静态变量。
  • 监视器对象:当一个线程执行同步代码块或同步方法时,会创建一个监视器对象来保存同步锁的信息。
  • 本地方法调用时使用的全局对象:在使用本地方法(native method)时,Java虚拟机可能会创建一些全局对象。

二、查看垃圾回收日志

要获取垃圾回收的详细信息,可以使用-verbose:gc参数。该参数提供了关于垃圾回收操作的详细日志输出。

-verbose:gc

通过使用此参数,可以获取有关垃圾回收的详细信息,包括每次垃圾回收的类型、回收前和回收后的内存使用情况等,这些信息对于分析和优化垃圾回收性能非常有用。


总结

JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了判断堆上的对象是否可以回收的方法(引用计数法、可达性分析法)、查看垃圾回收日志等内容,希望对大家有所帮助。

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

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

相关文章

【OCR项目】之用HALCON的深度学习工具进行文字识别,并导出到C++调用

前言 HALCON是一个强大的机器视觉工具,包含了2D,3D图像各种算子,以及各种任务的深度学习工具,包括目标检测,实例分割,文字识别等。 这次从实际生产的角度,来分享一下如何用HALCON进行文字识别…

Modbus网关BL101 既实现Modbus转MQTT,还能当串口服务器使用

随着工业4.0的迅猛发展,人们深刻认识到在工业生产和生活中,实时、可靠、安全的数据传输至关重要。在此背景下,高性能的工业电力数据传输解决方案——协议转换网关应运而生,广泛应用于工业自动化系统、远程监控和物联网应用应用环境…

持续集成工具Jenkins的使用之安装篇(一)

Jenkins是一个基于Java开发的开源的一种持续集成工具,主要用于环境部署,监控重复性的工作,旨在提供一个开放易用的软件平台,使软件项目可以进行持续集成。要想使用它,你就必须的先安装,接下来我们就介绍下J…

ctfshow-反序列化(web267-web270)

目录 web267 web268 web269 web270 总结 web267 页面用的什么框架不知道 看源码看一下 框架就是一种软件工具,它提供了一些基础功能和规范,可以帮助开发者更快地构建应用程序。比如Yii框架和ThinkPHP框架就是两个流行的PHP框架,它们提供…

【Linux多线程】生产者消费者模型

目录 生产者消费者模型 1. 生产者消费者模式的概念 2. 生产者消费者模型优点 ​编辑3. 生产者消费者模型的特点 基于BlockingQueue(阻塞队列)的生产者消费者模型 1.BlockingQueue 2. 使用CSTL中的queue来模拟实现阻塞队列 3. 基于任务的生产者消费…

html 会跳舞的时间动画特效

下面是是代码&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"> <head> <meta h…

Spring Boot3.2.2整合MyBatis Plus3.5.5

目录 1.前置条件 2.导坐标 3.配置数据源 4.配置mapper扫描路径 5.MyBatis Plus代码生成器整合 1.导坐标 2.编写代码生成逻辑 1.前置条件 已经初始化好一个spring boot项目且版本为3X&#xff0c;项目可正常启动 2.导坐标 <dependency><groupId>com.baomid…

Mysql-全局锁、表锁、行锁

本文已收录于专栏 《数据库》 目录 全局锁概述说明开启方式应用场景 表锁概念说明实现方式意向锁 开启方式 行锁概念说明实现方式记录锁&#xff1a;间隙锁临键锁 总结提升 全局锁 概述说明 全局锁是是对整个数据库实例加锁&#xff0c;加锁后整个实例就处于只读状态&#xff…

PySide6/PyQt6中Qt窗口标志/窗口属性汇总,如何正确的设置窗口标志/窗口属性

文章目录 📖 介绍 📖🏡 环境 🏡📒 使用方法 📒📚 窗口标志汇总📚 窗口属性汇总📝 使用方法📝 注意事项⚓️ 相关链接 ⚓️📖 介绍 📖 在Qt框架中,窗口标志(window flags)是用于控制窗口的各种属性和行为的强大工具。它们通过设置窗口的属性,如边框…

eNSP学习——配置通过STelnet登陆系统

可运行的topo不知道为什么无法上传&#xff0c;有需要的话&#xff0c;可以评论或私信文章标题获取相应的资源&#xff0c;也可评论“日常实验”获取常用的实验&#xff08;大概有一百个左右&#xff0c;里面有各种功能的单独配置&#xff0c;也有综合实验&#xff09;。 由于T…

JUC并发编程与源码分析学习笔记(二)

二十九、多线程锁之线程锁知识概述 说说Java“锁”事 从轻松的乐观锁和悲观锁开讲 通过8种情况演示锁运行案例&#xff0c;看看我们到底锁的是什么 公平锁和非公平锁 可重入锁&#xff08;又名递归锁&#xff09; 死锁及排查 写锁&#xff08;独占锁&#xff09;/读锁&a…

【每日一题】670. 最大交换-2024.1.22

题目&#xff1a; 670. 最大交换 给定一个非负整数&#xff0c;你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释: 交换数字2和数字7。示例 2 : 输入: 9973 输出: 9973 解释: 不需要交换。注意: 给定数字的范围是 [0, 1…