首页
首页 教程 派聪明
  • 首页
  • 教程
  • 派聪明
  • 登录
登录技术派畅享更多权益

用户名密码登录

其他登录:
icon_GitHubCreated with sketchtool.
绑定星球,畅享VIP服务

微信扫码/长按识别登录

输入验证码
有效期五分钟 👉 手动刷新

登录即同意 用户协议 和 隐私政策

绑定二哥编程星球,畅享 VIP 尊享服务!

戳我了解如何获取星球编号,新窗口打开

添加二哥微信 itwanger 审核更快

记得备注 星球编号
我会根据星球编号进行审核
1
大白话带你认识JVM
更新时间: 2024年01月16日
星球
2
JVM是如何运行Java代码的?
更新时间: 2024年01月16日
星球
3
Java的类加载机制
更新时间: 2024年01月16日
星球
4
Java的类文件结构
更新时间: 2024年01月16日
星球
5
从javap的角度轻松看懂字节码
更新时间: 2024年01月16日
星球
6
栈虚拟机与寄存器虚拟机
更新时间: 2024年01月16日
星球
7
字节码指令详解
更新时间: 2024年01月16日
星球
8
深入理解JVM的栈帧结构
更新时间: 2024年01月16日
星球
9
深入理解JVM的运行时数据区
更新时间: 2024年01月16日
星球
10
深入理解JVM的垃圾回收机制
更新时间: 2024年01月16日
星球
11
深入理解 JVM 的垃圾收集器
更新时间: 2024年01月16日
星球
12
Java 创建的对象到底放在哪?
更新时间: 2024年01月16日
星球
13
深入理解JIT(即时编译)
更新时间: 2024年01月16日
星球
14
JVM 性能监控之命令行篇
更新时间: 2024年01月16日
星球
15
JVM 性能监控之可视化篇
更新时间: 2024年01月16日
星球
16
阿里开源的 Java 诊断神器 Arthas
更新时间: 2024年01月16日
星球
17
内存溢出排查优化实战
更新时间: 2024年01月16日
星球
18
CPU 100% 排查优化实践
更新时间: 2024年01月16日
星球
19
JVM 核心知识点总结
更新时间: 2024年01月16日
星球
20
K个一组翻转链表
更新时间: 2024年02月07日
星球
关注公众号
原创
第十节:深入理解垃圾回收机制

记得以前有这样一副动图,用来嘲笑 JVM 的垃圾回收机制,大致的意思就是,JVM 的垃圾回收机制很工业化,但是好像是在做无用功,垃圾回收不彻底(😂)。

C/C++ 虽然需要手动释放内存,但开发者信誓旦旦,认为自己一定能清理得很彻底。那这次,我们就从头到尾来详细地聊一聊 JVM 的垃圾回收机制,看看到底如何。

垃圾回收的概念

垃圾回收(Garbage Collection,GC),顾名思义就是释放垃圾占用的空间,防止内存爆掉。有效的使用可以使用的内存,对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收。

Java 语言出来之前,大家都在拼命的写 C 或者 C++ 的程序,而此时存在一个很大的矛盾,C++ 等语言创建对象要不断的去开辟空间,不用的时候又需要不断的去释放空间,既要写构造函数,又要写析构函数。

构造函数和 Java 中的构造方法类似,用来创建对象,析构函数和 Java 中的 finalize 方法有一点类似,可以在对象被垃圾回收器回收之前执行清理操作,但不推荐,因为 finalize 的执行时机并不确定。

于是,有人就提出,能不能写一段程序实现这块功能,每次创建对象、释放内存空间的时候复用这段代码?

牛人还是多啊,1960 年,基于 MIT 的 Lisp 首先提出了垃圾回收的概念,用于处理 C 语言等不停的析构操作,Java 的垃圾回收机制算是发扬光大了。

Lisp 是一种函数式编程语言,我从官网上截幅图大家感受下。

垃圾判断算法

既然 JVM 要做垃圾回收,就要搞清楚什么是垃圾,什么不是垃圾。通常会有这么几种算法来确定一个对象是否是垃圾,这块也是面试当中常考的一个知识点,大家一定要掌握。

  • 引用计数算法
  • 可达性分析算法
  • 分代收集算法
  • 复制算法

引用计数算法

引用计数算法(Reachability Counting)是通过在对象头中分配一个空间来保存该对象被引用的次数(Reference Count)。

如果该对象被其它对象引用,则它的引用计数加 1,如果删除对该对象的引用,那么它的引用计数就减 1,当该对象的引用计数为 0 时,那么该对象就会被回收。

String s = new String("沉默王二");

我们来创建一个字符串,这时候"沉默王二"有一个引用,就是 s。此时 Reference Count 为 1。

然后将 s 设置为 null。

s = null;

这时候"沉默王二"的引用次数就等于 0 了,在引用计数算法中,意味着这块内容就需要被回收了。

引用计数算法将垃圾回收分摊到整个应用程序的运行当中,而不是集中在垃圾收集时。因此,采用引用计数的垃圾收集不属于严格意义上的"Stop-The-World"的垃圾收集机制(随后我们会细讲)。

引用计数算法看似很美好,但实际上它存在一个很大的问题,那就是无法解决循环依赖的问题。来看下面的代码。

public class ReferenceCountingGC {

    public Object instance;  // 对象属性,用于存储对另一个 ReferenceCountingGC 对象的引用

    public ReferenceCountingGC(String name) {
        // 构造方法
    }

    public static void testGC() {
        // 创建两个 ReferenceCountingGC 对象
        ReferenceCountingGC a = new ReferenceCountingGC("沉默王二");
        ReferenceCountingGC b = new ReferenceCountingGC("沉默王三");

        // 使 a 和 b 相互引用
        a.instance = b;
        b.instance = a;

        // 将 a 和 b 设置为 null
        a = null;
        b = null;

        // 这个位置是垃圾回收的触发点
    }
}

代码中创建了两个 ReferenceCountingGC 对象 a 和 b。

然后使它们相互引用。接着,将这两个对象的引用设置为 null,理论上它们会在接下来被垃圾回收器回收。但由于它们相互引用着对方,导致它们的引用计数永远都不会为 0,通过引用计数算法,也就永远无法通知 GC 收集器回收它们。

可达性分析算法

可达性分析算法(Reachability Analysis)的基本思路是,通过一些被称为引用链(GC Roots)的对象作为起点,然后向下搜索,搜索走过的路径被称为(Reference Chain),当一个对象到 GC Roots 之间没有任何引用相连时,即从 GC Roots 到该对象节点不可达,则证明该对象是需要垃圾收集的。

通过可达性算法,成功解决了引用计数无法解决的问题-“循环依赖”,只要你无法与 GC Root 建立直接或间接的连接,系统就会判定你为可回收对象。

在 Java 语言中,可作为 GC Root 的对象包括以下 4 种:

  • 虚拟机栈中引用的对象
  • 本地方法栈引用的对象
  • 类静态变量引用的对象
  • 常量引用的对象

已加入二哥编程星球,即刻绑定星球编号解锁🔐

该文档仅「二哥编程星球」的VIP用户可见

二哥的编程星球内容包括:

1. 付费文档: 技术派、MYDB 等项目配套的 120+篇教程查看权限

2. 面试指南: 校招、社招的 40 万+字面试求职攻略

3. 智能助手: 无限期使用派聪明 AI 助手,已对接讯飞星火和 ChatGPT双通道,不用花 1 分钱

4. 专属问答: 向二哥 1v1 发起提问,内容不限于 offer 选择、学习路线、职业规划等

5. 简历修改: 提供简历修改服务,附赠星球 100+优质简历模板可供参考

6. 学习环境: 打造一个沉浸式的学习环境,有一种高考冲刺、大学考研的氛围


二哥的星球

》步骤①:微信扫描上方二维码,点击「加入知识星球」按钮

》步骤②:访问星球置顶帖球友必看: https://t.zsxq.com/11rEo9Pdu,获取项目配套文档的语雀访问地址和密码

已加入星球,绑定星球编号
删除提醒

确定删除《第十节:深入理解垃圾回收机制》吗

真诚点赞 诚不我欺

回复