一起学习GC算法(图文详解)

举报
辰兮 发表于 2022/03/23 00:03:43 2022/03/23
【摘要】 【辰兮要努力】:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行! 博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端、后台、...

【辰兮要努力】:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行!

博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端、后台、数据库、项目案例等相关知识点总结,感谢你的阅读和关注,希望我的博客能帮助到更多的人,分享获取新知,大家一起进步!

吾等采石之人,应怀大教堂之心,愿你们奔赴在各自的热爱中…


一、文章序言

GC(Garbage Collection):JAVA/.NET中的垃圾回收器。Java是由C++发展来的。它摈弃了C++中一些繁琐容易出错的东西。其中有一条就是这个GC。


Java语言的一个显著优点就是引入垃圾回收机制,在一定程度上解决了内存管理的问题。

垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存;


垃圾回收机制的原理是什么呢?
在这里插入图片描述

其实垃圾回收机制的原理就是利用一些算法进行内存的管理,从而有效的防止内存泄漏、有效的利用空闲空间(内存空间)。


二、GC算法

Java语言规范没有明确的说明JVM 使用哪种垃圾回收算法,但是任何一种垃圾回收算法一般要做两件基本事情:

1、找到无用的对象;

2、回收将无用对象占用的内存空间。使该空间可被程序再次使用;

找到回收对象---->何时回收---->如何回收---->释放


如何找到这些无用的对象呢?

1、计数法(Reference Counting Collector)

给对象添加一个计数器,如果被引用则计数器加一;如果引用释放,计数器减一。当计数器为零时,代表该对象没有被引用那就需要回收了。

如果两个对象互相引用怎么办?比如A引用了B,B又引用了A,A.reference=B;B.reference=A,那就无法释放。因此该算法未被采用。

这个方法Java没有采用,但是Python用的是这种算法。

总结 解释
优点 引用计数收集器可以很快的执行,交织在程序运行中。对程序需要不被长时间打断的实时环境比较有利
缺点 无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为0

2.根搜索算法

(可达性分析)设立若干种根对象,当任何一个根对象到某一个对象都无法可达时,那么这个对象就是可回收的。
在这里插入图片描述
如上图右侧白色部分则为根无法到达,即会被判断为垃圾回收对象

在JAVA语言中,可以当做GC roots的对象有以下几种:

1、虚拟机栈中的引用的对象。

2、方法区中的类静态属性引用的对象。

3、方法区中的常量引用的对象。

4、本地方法栈中JNI的引用的对象。

第一和第四种都是指的方法的本地变量表,第二种表达的意思比较清晰,第三种主要指的是声明为final的常量值。


常见的GC算法?

在这里插入图片描述

1、copying算法(Compacting Collector)

简单的说就是:先找传不可回收的对象,将这些对象放一边,然后将可以回收的对象一起扫走!

在这里插入图片描述
复制算法将内存划分为两个区间,在任意时间点,所有动态分配的对象都只能分配在其中一个区间(称为活动区间),而另外一个区间(称为空闲区间)则是空闲的。

当有效内存空间耗尽时,JVM将暂停程序运行,开启复制算法GC线程。接下来GC线程会将活动区间内的存活对象,全部复制到空闲区间,且严格按照内存地址依次排列,与此同时,GC线程将更新存活对象的内存引用地址指向新的内存地址。

复制算法要想使用,最起码对象的存活率要非常低才行,而且最重要的是,我们必须要克服50%内存的浪费。


2、标记-清除算法。

标记-清除算法采用从根集合进行扫描,对存活的对象对象标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收,如图所示。

在这里插入图片描述
标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记-清除算法直接回收不存活的对象,因此会造成内存碎片。

这样坏处是会产生很懂不连续的内存碎片,比如你要找一个4K存储,当前一个小方格1K的存储,如果找不到再会触发一次GC!

总结:先标记----再清除


3、标记-整理算法

标记-整理算法采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的指针。标记-整理算法是在标记-清除算法的基础上,又进行了对象的移动,因此成本更高,但是却解决了内存碎片的问题

在这里插入图片描述
总结:先标记----再清除----再整理


4、generation算法(Generational Collector)

分代回收算法:其实我们要了解大部分对象都是朝生夕死(90%)

分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率。
在这里插入图片描述

拓展ps:
①Eden区(80%)和两块Survivor区(10%),堆中新生代和老年代占比1:2
②每次使用Eden和一块Survivor,回收时,将存活的对象一次性复制到另一块Survivor上,如果另一块Survivor空间不足,则使用分配担保机制存入老年代,什么时候从Survivor进入老年代,视垃圾回收器类型而定。

过程:将堆分为新生代和老年代,根据区域特点选用不同的收集算法,如果新生代朝生夕死,则采用复制算法,老年代采用标记清除,或标记整理


三、拓展小结

最后我用思维导图总结一下本篇文章,我们一起回顾一下是否还记得相关重点!

在这里插入图片描述
具体的每一个算法的优缺点都在图中,如有问题欢迎沟通交流!


拓展小结:关于根搜索算法小结

1、根搜索算法解决的是垃圾搜集的基本问题,也是最关键的问题,就是哪些对象可以被回收;

2、垃圾收集显然还需要解决什么时候回收、以及如何回收;

3、在根搜索算法的基础上,现代虚拟机的实现当中,垃圾搜集的算法主要有三种,分别是标记-清除算法、复制算法、标记-整理算法,这三种算法都扩充了根搜索算法;


本文只是简单的介绍GC,还有更多的关于虚拟机调优的相关问题值得我们探索和学习!


The best investment is to invest in yourself.

在这里插入图片描述

2020.09.20 愿你们奔赴在自己的热爱里!

文章来源: blessing.blog.csdn.net,作者:辰兮要努力,版权归原作者所有,如需转载,请联系作者。

原文链接:blessing.blog.csdn.net/article/details/108691358

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。