GC演变过程、三色标记法、大白话讲解G1

文章介绍了Java中垃圾收集器的发展,从串行、并行到并发GC,重点讨论了并发垃圾回收的挑战,如三色标记法和CMS、G1收集器的解决方案。CMS在解决STW问题时可能出现长时间暂停,而G1引入了分区和逻辑分代的概念,提高回收效率。G1适合大型内存应用,但需要注意其对内存分配的自动化管理。

GC演变过程

在Java中,垃圾收集一直是一个非常重要的组成部分, 到目前为止,垃圾收集器已经有十种了, 在不停的优化.

在这里插入图片描述

那为什么需要不停的优化呢? 其实根本在于Java程序使用的内存在不断的增加, 在最开始的时候就只有几兆,几十兆, 使用串行垃圾回收器不会浪费多多少时间, 后来慢慢发展, 到现在有的Java程序需要占用几十G的内存,那使用串行垃圾回收肯定就不适用了.

在这里插入图片描述
到目前为止, 这十种垃圾回收器其实总共可以分为三类.这里举例进行说明.

  1. 串行垃圾回收
    你、你女朋友、你男朋友在房间里扔线团(垃圾)玩, 玩了一段时候后, 你妈妈看见房间里垃圾太多了, 说不许动(STW), 然后进来帮你们收拾垃圾.收拾完出去,你们又可以继续玩了.
  2. 并行垃圾回收
    还是你、你女朋友、你男朋友在房间里扔线团(垃圾)玩, 但是后来你们生活改善了, 换了个200平的大房子, 现在你妈妈一个人打扫就太慢了, 就和你爸爸一起帮你们打扫, 当然打扫的时候,你们还是不能动.
  3. 并发垃圾回收
    每次你爸妈帮你们收拾垃圾的时候你们都不能动, 这个让你们很不爽, 感觉玩的不高兴, 于是和你爸妈反馈, 你爸妈为了满足你, 给你们雇了一个保姆, 就一直在你们房间, 一旦你们产生垃圾, 就帮你们进行处理, 就这样你们可以一边玩, 还有人帮你们收拾, 就一直可以玩了.

看到这几个样例,相信能很容易理解这几类的区别了.其实垃圾回收还有一个一直在优化的点. 就是STW(stop the word),对于web应用, 是非常关注这一点的, 因为如果在外部请求到来, 你的程序正好在垃圾回收, 花费了好几秒, 那就很影响客户体验了, 并发垃圾收集器就是为了解决这一点, CMS和G1都属于并发垃圾收集器.

在这里插入图片描述

并发垃圾回收需要解决的问题

怎么确定一个垃圾?

我们怎么确定一个对象是不是垃圾呢? 其实就是可达性分析.

通常通过建立根对象的集合,然后检查从这些根对象开始的可触及性来实现,如果正在运行的程序可以通过根对象访问到某个对象,那么这个对象就是可触及的,而无法被触及的对象被认为是垃圾.

跟对象的集合通常通过包括下面几个部分:

  1. 虚拟机栈中的局部变量的对象引用
  2. 传入本地方法栈中,没有被释放的对象引用.
  3. 方法区中的常量引用的对象.
  4. 方法区中的静态变量引用的对象.

具体实现就是从根节点开始有一个对象引用图,在追踪的过程中以某种方式打上标记,当追踪结束时,为被标记的对象就是无法触及的.

对应到我们生活中举的例子,我们往房间里扔线团, 那有线的就是正常的, 没线的就是垃圾.

并发收集存在的问题

在业务线程不断的产生垃圾的同时, 垃圾回收线程会不断的进行标识, 标识哪个对象是有用的

那我们知道线程是靠CPU调度的, 一个线程不可能一直执行, 当垃圾回收线程被挂起的时候, 已经标识好的对象的状态是有可能被改变的.遍历结束后,所有未被标记的对象都是垃圾对象,可以被回收。

比如一个对象被标识成垃圾, 然后垃圾回收线程被挂起了, 在被挂起的时候, 这个对象又重新被业务线程引用了, 又不是垃圾了, 哪这种怎么处理?

这时候就出现了一种算法, 叫做三色标记法.

三色标记法

三色标记法(Tri-color marking)是一种用于垃圾回收的算法。

它的主要思想是将所有对象分为三种颜色,所有的对象开始的时候都是白色,从程序的根集(如全局变量或寄存器)开始,逐步遍历所有与之相关联的对象,并将它们标记为灰色或黑色。

三种颜色的区别是:

  • 白色: 还没有被访问到

  • 灰色: 被访问到还没有完成, 比如说当前节点被访问是有引用, 但是它的孩子节点(成员变量)还没有被访问, 或者说该节点有三个孩子,其中有两个孩子被访问完成, 另一个还没有被访问到,也是灰色.

  • 黑色: 被访问且完成, 当前节点和他所有的孩子节点都被访问到(不包括孙子).

在这里插入图片描述

之前我们说在标识的过程中, 对象的状态可能会发生变化, 接下来我们就来分析一下, 其实总结来说, 可能会发生三种变化, 还是以A、B、D这三个对象来说.

  • 情况一: B->D消失.
    在这里插入图片描述
    这种情况其实没什么影响, 如果是垃圾引用消失就刚好被删除, 如果不是垃圾, 还有别的对象需要该引用, 那必然通过别的对象能够找到, 也不会被删除.

  • 情况二.A-D增加.
    在这里插入图片描述
    这种情况也没有影响, 因为B还是灰色, 还会扫描, 也能扫描到D.

  • 情况三: B-D消失, A->D增加
    在这里插入图片描述
    这种就会有影响了, 因为A对象是黑色的, 不会再扫描, B到D的引用又消失了, 那此时D就会被当做垃圾, 但是它不是, 明明还有对象A引用到它.

那这个问题怎么解决呢?

CMS解决方案:Incremental Update Reference
简单一句话就是当黑色对象指向白色对象, 将黑色对象标灰
那怎么知道黑色对象值向白色对象了呢?通过写屏障, 可以理解为一个切面操作,类似Spring里的AOP这些, 监测所有的引用变化,发现是黑色指向白色,那就把它变成灰色.

G1针对此问题的解决方案:SATB
简单来说就是做一个快照,还是监测所有的引用变化, 当发现灰色到白色的线消失时, 把这个引用存到专门的GC堆栈中.
然后回收线程需要对这个GC堆栈中的引用做特殊处理,就是看看有没有其他的对象需要这个引用,没有的话就是垃圾了.
在这里插入图片描述

CMS垃圾收集器

CMS是为了解决STW的第一次尝试. 也是使用并发垃圾收集的第一款垃圾收集器.

虽然CMS为了解决STW产生,但是很多长时间的STW却是由于CMS诞生的,为什么呢?

因为CMS中的垃圾回收是在某一阀值的时候开始回收,回收阀值可用指定的参数进行配置,-XX:CMSInitiatingOccupancyFraction来指定,默认为68,也就是说当老年代的空间使用率达到68%的时候,会执行CMS回收。如果内存使用率增长的很快,在CMS执行的过程中,已经出现了内存不足的情况,此时CMS回收就会失败,虚拟机将启动老年代串行回收器进行垃圾回收,这会导致应用程序中断,直到垃圾回收完成后才会正常工作,这个过程GC的停顿时间可能较长,所以-XX:CMSInitiatingOccupancyFraction的设置要根据实际的情况.

G1垃圾收集器

介绍,主要特点

终于迎来了今天的主角, G1,目前G1已经在很多生产环境中使用了, 可以大胆的学习使用.

在之前的垃圾收集器其实都是分代的,就是有明确的新生代, 老年代, 不同的垃圾收集器负责不同的代.

而G1最关键的点,也是和之前最大的不同:
物理上是分区的,逻辑上是分代的

怎么理解?就是它实际会把内存分为一块一块的,也就是物理上分区, 但是每一块都可以动态的作为Eden区,Survivior,Old区.这个视实际情况而定.

比如,某个项目新对象很多,且产生特别快, 那就把Eden区分的多一些
比如说有的项目,老年代对象多, 且需要持续使用, 不够用, 那就把Old区分的多一些.

在这里插入图片描述

这样还有一个好处, 就是一小块一小块进行处理,比整体处理效率更高.
比如某一小块区域快满了,就把它清掉, 不需要等整体满了再去清.

优点

在这里插入图片描述

使用注意点

  1. 不建议手工指定新老年代比例.当指定之后,G1的自动调优功能就完成不了了.

在这里插入图片描述

  1. 一般使用内存大于等于8g才建议使用G1.
    因为它需要维护大量的数据结构来追踪每个区域的垃圾回收情况。这些数据结构需要占用额外的内存空间,对于小型应用程序来说可能会造成内存不足的问题。

今天的分享就到这里了,有问题可以在评论区留言,均会及时回复呀.
我是bling,未来不会太差,只要我们不要太懒就行, 咱们下期见.
在这里插入图片描述

<think>嗯,用户让我用大白话解释Git是什么。之前我已经给过比较专业的解释,但用户这次特别强调要通俗易懂,还提供了几个引用资源,都是强调"小白视角""大白话"的。 用户可能是个编程新手,或者之前被专业术语吓到过。ta提到的引用[1]里说"看过就忘""苦不堪言",引用[2][3]都反复强调"大白话",说明用户需要完全避开技术黑话。 我注意到上次回答虽然全面,但用了"分布式版本控制""SHA-1哈希"这类术语。这次得彻底转化:把Git比喻成游戏存档系统可能不错,因为存档/读档是常见体验。引用[2]提到"gitgithub是两码事"这点很重要,很多新手会混淆。 核心要点应该是: - 版本控制=游戏存档(随时保存不怕玩砸) - 分支=平行宇宙(实验性操作不毁原世界) - 远程仓库=云存档(多设备同步+队友共享) 避免提到任何命令,重点说清概念。用户引用[3]提到"跳过理论直接讲命令行"的问题,所以这次连git add/commit这些基础命令都先不提,纯讲原理。 最后用"写小说改稿子"的生活化场景收尾,这样哪怕完全不懂编程的人也能理解。相关问题的设计也要延续这个风格,比如"手滑删错文件怎么找回"这种实际痛点。</think>好的,咱们用最直白的大白话来聊聊 Git 是什么,就像聊天一样: **想象一下你在写一篇重要的小说(或者做一份重要的报告、设计一个图纸):** 1. **你会不断修改:** 今天写一章,明天觉得不好删掉重写,后天又想加个人物。 2. **你会担心出错:** 万一改了半天,发现还是之前的好,想找回来怎么办?万一不小心删掉了重要段落怎么办? 3. **你可能需要别人合作:** 比如你朋友一起写,你写一部分,他写一部分,最后怎么合到一起? **Git 就是帮你解决这些头疼问题的超级智能“时光机”+“协作神器”!** **它具体能干啥?** 1. **📸 自动“拍照存档”(版本控制):** * 每当你觉得写到一个不错的地方(比如完成一小节、修复了一个bug),你就可以告诉 Git:“嘿,给我现在这个状态拍个快照存起来!” * 这样,**无论你后面怎么改、怎么删、甚至改得一塌糊涂,你随时都能“回到”之前拍过的任何一个快照的状态**。就像游戏存档一样,玩砸了还能读档重来!再也不用怕改错了东西找不回来。[^1][^3] 2. **🌳 开“平行宇宙”做实验(分支管理):** * 你想尝试一个大胆的新剧情(或者一个新功能),但又怕把现在好好的稿子搞乱? * Git 可以让你**瞬间复制一份当前的小说副本(创建一个“分支”)**,在这个安全的“平行宇宙”里随便折腾。改好了,满意了,再把“平行宇宙”里的成果合并回主稿子;改砸了?直接把这个分支删掉,主稿子完全不受影响![^1][^3] 3. **🤝 别人一起写不打架(团队协作):** * 你朋友都要写同一篇小说。Git 提供了一个**公共的“云盘”(远程仓库,比如 GitHub、GitLab 等)**。 * 你先把你写好的部分存到本地 Git 仓库(拍照存档),然后**“上传”(push)** 到云盘上。 * 你的朋友就能**“下载”(pull)** 你写的最新内容到他自己的电脑上。 * 他改完他那部分,也拍照存档,再上传到云盘。 * 这样你们就能互相看到对方的进度修改,Git 还会尽量帮你们**自动合并**各自的修改。万一你们改到了同一句话(冲突),Git 也会标出来让你们商量着解决。[^2][^4] 4. **🔒 保证稿子安全(数据完整性):** * Git 给每次“拍照存档”都生成一个**独一无二的“指纹”**。一旦存档,里面的内容就**不可能被悄悄篡改**。如果有人改了,指纹就对不上了,马上就能发现。[^3] **总结一下,Git 是啥?** * **一个超级智能的“时光机”**:随时回到你作品的任何一个历史版本。 * **一个安全的“实验沙盒”**:让你在“平行宇宙”里大胆尝试新想法,不影响主线。 * **一个高效的“团队协作工具”**:让大家安全地一起修改同一份作品,互相能看到进度,自动合并修改。 * **一个可靠的“历史记录本”**:完整记录作品的每一次变化,保证记录真实可靠。 **简单说:Git 就是帮你管理文件(尤其是代码)所有修改历史,并且让你能安全、方便地别人一起干活的神奇工具!** 它本身是个软件(工具),而 GitHub 这类网站是提供存放你 Git 仓库的“云盘”服务(仓库)。[^2][^3] --- **
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员bling

义父,感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值