一起学习GC算法(图文详解)
【辰兮要努力】: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
- 点赞
- 收藏
- 关注作者
评论(0)