GC:你要用什么方式把我丢掉?(1)

大家都知道Java程序的运行离不开java虚拟机,而Java虚拟机(HotSport VM)运行时的数据区大致可分为五个部分,分别为JAVA栈、本地方法栈、堆、方法区、程序计数器,其中JAVA栈、本地方法栈、程序计数器是线程私有的,方法区和堆是线程共享区。

堆中一般保存着所有引用类型的真实信息(即对象)、字符产常量池、静态变量,以方便执行器执行。

而堆的空间是有限的,JVM虚拟机又有何保证存储空间的充足的呢?这就需要用的垃圾回收机制

本文主要讲解GC清理垃圾常用的四种算法

垃圾回收机制(GC)

=========================================================================

当对象被创建时,就会在Java虚拟机的堆区拥有一块内存,在Java虚拟机的生命周期中,Java程序会陆续地创建无数个对象,加入所有的对象永久的占用内存,那么内存有可能很快被消耗光,最后引发内存空间不足的错误。因此必须采取一种措施来及时回收那些无用对象的内存,以保证内存可以被重复利用。

JAVA GC 机制,是Java与C++/C的主要区别之一,作为java开发者,一般不需要战门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题。

那GC常用的算法有哪些呢?

GC常用算法

=====================================================================

  • 标记-清除算法

  • 标记-压缩算法

  • 复制算法

  • 分代收集算法

标记清除算法


Step 1:标记(Marking):

GC通过遍历内存区辨别哪些内存在使用,哪些内容没有使用。并做好标记。

在这里插入图片描述

引用的对象以蓝色显卡。未引用的对象以金色显示。在标记阶段扫描所有对象以进行此确定。如果必须扫描系统中的所有对象,这可能是一个非常耗时的过程。

Step 2:清除(Normal Deletion):

清除阶段移除掉对象垃圾,并且用一个链表维护空闲的区域

在这里插入图片描述

内存分配器持有空闲内存区的引用,以便分配内存给新的对象

优点:

每个活着的对象的引用只需要找到即可,找到一个就可以判断它为活得。不用移动对象的位置。

缺点:

  • 效率比较低(递归与全堆对象遍历),每个活着的对象都要在标记阶段遍历一遍。

  • 所有对象都要在清除阶段扫描一遍,算法复杂度高。

  • 没有移动对象,导致可能出现需要碎小的空间无法利用(可能导致空间利用率低)。

标记-压缩算法


基于标记-清除法的缺点—无法利用碎小的空间,提出了我们的标记-压缩算法。不同之处在于在第二个阶段,该算法并没有直接堆死亡的对象进行清理,而是将所有存活的对象进行整理,放在同意区域的另一处空间,然后把剩下的所有对象全部清除,这样就达到了标记-整理的目的。

在这里插入图片描述

通过一起移动引用的对象,这使得新的内存分配更容易和更快

优点:

不会产生大量的碎片空间

缺点:

如果存活的对象过多,整理阶段就会执行较多复制操作,导致算法效率低。

复制算法


复制算法与标记-压缩算法的不同之处在于不是在同一个区域进行复制,而是将所有存活的对象复制到另一个区域

该算法将内存平均的分为两个部分,然后每次使用其中的一部分,当这部分内存存满的时候,将内存中所有存活的对象复制到另一个内存中,然后将之前的内存清空,只是用这部分内存,然后循环。

在这里插入图片描述

优点:

实现简单,不产生内存碎片

缺点:

每次运行,总有一半内存是空的,导致内存的利用率只有50%。

分代收集算法


标记和压缩算法存在的问题

标记和压缩算法对java虚拟机而言会比较耗时。当java虚拟机分配了越来越多的对象之后,GC就会花费更多的时间。然而,绝大多数的对象存活时间都比较短。这样我们可以把存活时间长的对象和短的对象隔离开。GC就会拥有更高的效率。

在这里插入图片描述

Y轴显示分配的字节数,X访问显示随时间分配的字节数。

随着时间的推移,分配的对象越来越少。事实上,大多数物体的寿命都很短。

现在的虚拟机GC大多数采用分代收集算法,它根据对象的生存周期,将堆分为新生代和老年代。

分代收集算法思想:

  • 在新生代中,由于对象生存期短,每次回收都会有大量的对象死去,那么这时就采用复制算法。

  • 老年代里的对象存活率高,没有额外的空间进行分配,所以可以使用标记-清除或者标记-压缩进行清除。

分代收集过程

  1. 新生代(Young)分为Eden区。From和To区

在这里插入图片描述

2.几乎所有新的对象都会在Eden空间分配内存,两个survivor空间一开始都是空的。

在这里插入图片描述

3.对着对象的不断创建,Eden区被填满

在这里插入图片描述

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!**

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

你看到的这段提示是 Git 输出的信息,说明你当前处于一种特殊的 **“分离头指针”状态(detached HEAD)**。我们来逐句解释它的含义,并告诉你该怎么做。 --- ### 🔍 原始输出解析: ```bash Warning: you are leaving 3 commits behind, not connected to any of your branches: 433ae4f 完成了alter_db的函数,支持表的升级 e0d31fe 正在做扩容的部分,process_db_is_full中输出的zone_id目前还有问题,主要原因是g_lay_info->zone_list是NULL 39c45eb 在更新uuid结构体时增加了raid的部分 If you want to keep them by creating a new branch, this may be a good time to do so with: git branch <new-branch-name> 433ae4f Switched to branch 'hsy_HEAD' ``` --- ## ✅ 这是什么意思? ### 1. **你正处于“detached HEAD”状态** - 表示你的 `HEAD`(Git 当前指向的位置)**不在任何一个分支上**。 - 通常是因为你执行了: - `git checkout <某个具体的提交哈希>`,比如 `git checkout 433ae4f` - 或者 `git checkout --detach ...` - 在这种状态下,你可以查看代码、编译、测试,但如果你提交新 commit,它不会属于任何分支。 ### 2. **你“离开”了 3 个提交** - Git 提醒你:有三个提交(从 `433ae4f` 开始)曾经可以被访问到,但现在你切换走了,它们将“悬空”(unreachable),除非你创建分支指向它们。 - 如果你不保存这些提交的引用,**未来 Git 可能会自动清理它们(通过 gc)**,导致丢失! ### 3. **Git 建议你创建一个新分支来保留这些提交** ```bash git branch <new-branch-name> 433ae4f ``` 意思是:创建一个新分支,让它指向 `433ae4f` 这个提交,这样你就不会丢掉这三条提交历史。 ### 4. **最后切换到了 `hsy_HEAD` 分支** ```bash Switched to branch 'hsy_HEAD' ``` 表示你现在已经在名为 `hsy_HEAD` 的分支上了。这个分支可能是你刚创建的,或者是已存在的。 --- ## ✅ 你现在面临的问题 > ❗ 那三个提交(包括你完成 `alter_db` 函数的重要工作)目前 **不属于任何分支**,如果不处理,**可能会永久丢失!** --- ## ✅ 如何拯救这些提交? 你需要立即创建一个分支,指向最顶端的那个提交(通常是第一个列出的,即 `433ae4f`)。 ### ✅ 步骤:创建分支来保护这些提交 ```bash git branch save-work-from-detach 433ae4f ``` 这会创建一个叫 `save-work-from-detach` 的分支,指向那个重要的提交。 然后你可以切换过去看看内容是否正确: ```bash git checkout save-work-from-detach ``` 或者直接合并进当前开发分支(如 `dev` 或 `hsy_HEAD`): ```bash git checkout hsy_HEAD git merge 433ae4f # 把那三个提交合并进来 ``` --- ## ✅ 推荐操作流程(现在应该做的事) ```bash # 1. 创建分支保存那三个提交 git branch feature/alter-db-and-more 433ae4f # 2. 切换到你的目标分支(假设是 hsy_HEAD 或 dev) git checkout hsy_HEAD # 3. 将那些提交合并进来 git merge 433ae4f # 4. 确认代码都回来了,一切正常 git log --oneline -5 ``` 之后你可以继续开发,不用担心丢失历史。 --- ## ✅ 如何避免下次再出现这个问题? - 不要直接用 `git checkout <commit-hash>` 查看旧代码。 - 如果必须查看某个提交,可以用: ```bash git show <commit-hash> ``` 或临时创建分支: ```bash git checkout -b temp-view 433ae4f ``` --- ## ✅ 总结 | 问题 | 解释 | |------|------| | 🤔 为什么会出现这个警告? | 因为你 checkout 到了一个具体提交,进入了 detached HEAD 状态 | | ⚠️ 有什么风险? | 你做的提交或原本可达的提交会“悬空”,可能被 Git 自动回收 | | ✅ 该怎么办? | **立刻创建分支指向这些提交**,例如 `git branch myfix 433ae4f` | | ✅ 后续怎么用? | 切换回正常分支并 merge,或将 HEAD 移回去 | --- ### 💡 补充建议 你可以运行以下命令确认那几个提交是否还能访问: ```bash git show 433ae4f # 查看具体内容 git log --oneline 433ae4f~3..433ae4f # 查看附近提交 ``` 只要还没被 `git gc` 清理,就还能救回来! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值