引用计数与可达性分析:谁死了,谁还活着?

垃圾回收,顾名思义,便是将已经分配出去的,但却不再使用的内存回收回来,以便能够再次分配。在Java虚拟机的语境下,垃圾指的是死亡的对象所占据的堆空间。这里便涉及了一个关键的问题:如何辨别一个对象是存是亡?

引用计数

引用计数(Reference Counting)是一种古老的辨别方法,它的基本思想是给每个对象添加一个引用计数器,每当有一个引用指向该对象时,计数器就加1;每当有一个引用停止指向该对象时,计数器就减1。当计数器的值变为0时,就表示没有任何引用指向该对象,因此该对象就成为垃圾,

引用计数的主要问题是无法处理循环引用(Reference Cycle)的情况。例如,如果对象A和对象B互相引用,那么即使没有其他引用指向它们,它们的引用计数器也不会变为0,因此它们不会被回收,这就导致了内存泄漏。这是引用计数最大的缺点,也是它在许多现代编程语言中不被使用的主要原因。

另外,引用计数需要在每次引用赋值时更新引用计数器,这会带来一定的性能开销。而且,如果多个线程同时修改同一个对象的引用计数器,还需要进行同步,这会进一步增加性能开销。

可达性分析

Java虚拟机的主要采取的是可达性分析(Reachability Analysis)。这个算法是通过一系列的称为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。

GC Roots通常是由堆外指向堆内的引用,包括以下几种。

1)虚拟机栈(栈帧中的本地变量表)中引用的对象;

2)方法区中类静态属性引用的对象;

3)方法区中常量引用的对象;

4)本地方法栈中JNI(即一般说的Native方法)引用的对象。

可达性分析可以解决引用计数所不能解决的循环引用问题。例如,即便对象A和B相互引用,只要从GC Roots出发无法到达A或者B,那么可达性分析便不会将它们加入存活对象合集之中。

尽管可达性分析的算法本身很直观,但在实际应用中,还需要解决一些其他问题,如误标和漏标。

1)误标:将已经不再使用的对象错误地标记为"活的"。例如,一个全局静态对象引用了一个已经不再需要的局部对象,它会被错误地标记为"活的"。

2)漏标:将仍在使用的对象错误地标记为"死的"。例如,在并发环境中,一个线程正在使用一个对象,而另一个线程正在进行垃圾回收。如果垃圾回收线程看到的是一个过时的对象引用关系,它可能会错误地认为一个正在使用的对象是"死的"。

误报可能导致Java虚拟机错过部分垃圾回收的机会。而漏报更麻烦,因为垃圾回收器可能会错误地回收仍被引用的对象内存。如果试图从原引用访问已经被回收的对象,可能会导致Java虚拟机崩溃。

Stop-the-world 以及安全点

为了避免这些问题,Java虚拟机的传统垃圾回收算法采用了Stop-the-world方式。在此阶段,Java虚拟机会暂停所有的应用线程,确保在垃圾回收过程中不会有新的对象被创建,也不会有对象引用关系的变化。但这会导致应用程序的响应时间增加,因为在这个阶段,所有的应用线程都被暂停,应用程序无法响应用户的请求。

安全点(Safe Point)是Java虚拟机用来控制Stop-the-World的一种机制。安全点是指那些可以安全地暂停应用线程的点。在这些点上,Java虚拟机可以确保对象引用关系不会发生变化。常见的安全点有方法调用(包括JNI方法调用)、循环跳转、异常抛出等。其中方法调用是一个很好的安全点,因为方法调用通常涉及到大量的对象引用操作。

对于解释执行,当有安全点请求时,Java虚拟机可以在每条字节码指令后面都设置一个安全点,但这种方式的开销很大。在执行即时编译器生成的机器码时,Java虚拟机通常会在方法的入口和退出处,以及循环的回边处设置安全点。另外当线程阻塞时,由于处于Java虚拟机线程调度器的掌控之下,因此可以设置安全点。

未完待续

很高兴与你相遇!如果你喜欢本文内容,记得关注哦

谁生?谁死?从引用计数到可达性分析,洞悉GC的决策逻辑的更多相关文章

  1. JVM中垃圾回收机制如何判断是否死亡?详解引用计数法和可达性分析 !

    因为热爱,所以坚持. 文章下方有本文参考电子书和视频的下载地址哦~ 这节我们主要讲垃圾收集的一些基本概念,先了解垃圾收集是什么.然后触发条件是什么.最后虚拟机如何判断对象是否死亡. 一.前言   我们 ...

  2. JVM 基础:回收哪些内存/对象 引用计数算法 可达性分析算法 finalize()方法 HotSpot实现分析

    转自:https://blog.csdn.net/tjiyu/article/details/53982412 1-1.为什么需要了解垃圾回收 目前内存的动态分配与内存回收技术已经相当成熟,但为什么还 ...

  3. java中垃圾回收机制中的引用计数法和可达性分析法(最详细)

    首先,我这是抄写过来的,写得真的很好很好,是我看过关于GC方面讲解最清楚明白的一篇.原文地址是:https://www.zhihu.com/question/21539353

  4. C++引用计数设计与分析(解决垃圾回收问题)

    1.引言 上一篇博文讲到https://www.cnblogs.com/zhaoyixiang/p/12116203.html 我们了解到我们在浅拷贝时对带指针的对象进行拷贝会出现内存泄漏,那C++是 ...

  5. Objective-C内存管理之引用计数

    初学者在学习Objective-c的时候,很容易在内存管理这一部分陷入混乱状态,很大一部分原因是没有弄清楚引用计数的原理,搞不明白对象的引用数量,这样就当然无法彻底释放对象的内存了,苹果官方文档在内存 ...

  6. 恒生UFX接口引用计数心得

    本文介绍在基于恒生T2SDK基础上开发对接UFX柜台时,有关引用计数的一些心得体会. 下面以配置接口和连接接口为例子来介绍,下面是文档介绍: 创建配置接口说明: 3.1.2 创建配置接口(NewCon ...

  7. obj-c编程11:内存管理和ARC(自动引用计数)

    乖乖隆地洞,这篇文章内容可是不得了,内存管理哦!首先,这个要是搞不明白,你就等着进程莫名其妙的挂死,或是疯狂申请内存却不释放,结果被OS杀死,不管是"自杀"还是"他杀&q ...

  8. ZT Android的引用计数(强弱指针)技术及一些问题

    Android的引用计数(强弱指针)技术及一些问题 分类: Android 2013-06-07 18:25 844人阅读 评论(4) 收藏 举报 目录(?)[+] Android C++框架层的引用 ...

  9. std::shared_ptr 和 std::weak_ptr的用法以及引用计数的循环引用问题

    在std::shared_ptr被引入之前,C++标准库中实现的用于管理资源的智能指针只有std::auto_ptr一个而已.std::auto_ptr的作用非常有限,因为它存在被管理资源的所有权转移 ...

  10. 2. 引用计数法(Reference Counting)

    1960年,George E. Collins 在论文中发布了引用计数的GC算法. 引用计数法意如了一个概念,那就是"计数器",计数器表示的是对象的人气指数, 也就是有多少程序引用 ...

随机推荐

  1. C#.NET制作DLL供DELPHI调用

    因为工作需求,本来想用C#做一个WebService,但是弄了两天没做成.于是想,反正都是我这一台电脑,做个DLL吧. 1 namespace U8Service 2 { 3 public inter ...

  2. InnoDB为什么不用跳表,Redis为什么不用B+树?

    要回答为什么 InnoDB(MySQL 的存储引擎) 使用 B+ 树而不是跳表(Skip List),以及为什么 Redis 使用跳表而不是 B+ 树,需要分析两者的数据结构特性.使用场景和设计目标. ...

  3. tryhackme - 导言

    官网:https://tryhackme.com/ 类似hackthebox的CTF风格黑客靶场(但区别于zseano提供的真是SRC风格(https://www.bugbountyhunter.co ...

  4. 一款基于 Ant Design 设计语言实现、漂亮的 .NET Avalonia UI 控件库

    前言 今天大姚给大家分享一款基于 Ant Design 设计语言实现.漂亮的 .NET Avalonia UI 控件库:AtomUI. AtomUI项目介绍 AtomUI 是一款基于 Ant Desi ...

  5. 重磅!Ollama发布UI界面,告别命令窗口!

    Ollama 终于提供 UI 界面了,再也不用在命令窗口中使用了,如下图所示: 什么是Ollama? Ollama 是一个开源的大型语言模型服务工具.它的主要作用是帮助用户快速在本地运行大模型,简化了 ...

  6. win10如何彻底关闭自带defender杀毒软件【教程详解】

    windows defender是win10系统自带的杀毒软件,有的时候我们需要关闭它才能运行某些软件,而网上的一些针对关闭win10自带的杀毒软件的方法似乎并没有什么效果,下面就来教大家彻底关闭wi ...

  7. G-SRv6实现原理及基本功能测试方法

    什么是G-SRv6? G-SRv6(Generalized Segment Routing over IPv6,通用SRv6)是一种兼容SRv6的通用机制,支持携带多种类型不同长度的SID,这些SID ...

  8. 本土优势驱动生态繁荣,Gitee迈向2025年中国代码托管市场领军者

    Gitee领跑中国代码托管市场:本土化优势与全球化野望 在中国数字化转型的浪潮中,代码托管平台正成为软件开发基础设施的关键一环.作为国内领先的代码托管平台,Gitee凭借其本土化优势和技术创新,不仅在 ...

  9. 搭建基于 Solon AI 的 Streamable MCP 服务并部署至阿里云百炼

    一.快速搭建 Solon 项目,引入 Solon AI 1. 开发环境准备 JDK 8 或以上版本. Maven 3.8.6 或以上版本. 通义千问 API Key(用于模型调用). 2. 创建名为 ...

  10. 题解:P12336 第三心脏

    题目链接. 作者没看过第三心脏,所以作者猜测第三个心脏应该是用铁做的,由于铁粉是黑的,所以这道题目是黑. 养成良好习惯,不留根号,式子变为: \[a^2+b^2+c^2+d^2=\left(a\opl ...