A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 执迷不悟 于 2020-4-22 17:41 编辑

                               垃圾回收常见算法
1、引用计数法
1.1 原理
        假设有一个对象A,任何对象对A进行引用,那么对象A的引用计数器+1,当引用失效时,对象A的引用计数器-1,当对象A的引用计数器为0时,就说明对象A没用被引用,那么就可以进行回收。
1.2 优缺点
优点:
  • 实时性高,不需要等到内存不足时,才开始回收,运行时判断对象计数器是否为0,进行回收。
  • 在垃圾回收过程中应用无需挂起,如果申请内存时,内存不足,则立即报outofmember 错误。
  • 区域性,更新对象计数器时,只会印象到该对象,不会扫描全部对象。

缺点
  • 每次对象都被引用,都需要去更新对象计数器,会增加时间开销。
  • 浪费CPU资源,因为内存足够是,对象计数器任然在运行进行统计。
  • 无法解决循环引用问题(最大缺点)

循环引用如:对象A维护了一个成员属性,类型是对象B,对象B中维护了一个成员属性,类型是对象A,然后分别给这两个成员属性赋值,在将对象A赋值为null,将对象B赋值为null,这样对象A和对象B就都是null,但是a和b存在引用关系,这样a和b永远不会被回收。
2、标记清除法
标记清除算法,是将垃圾回收分为两个阶段,分别是标记和清楚
  • 标记:从跟节点开始标记引用的对象
  • 清除:未被标记引用的对象就是垃圾对象,可以被清理

2.1、原理
这张图代表的是程序运行期间所有对象的状态,它们的标志位全部是0(也就是未标记,以下默认0就是未标记,1为已标记),假设这会儿有效内存空间耗尽了,JVM将会停止应用程序的运行并开启GC线程,然后开始进行标记工作,按照根搜索算法,标记完以后,对象的状态如下图。
可以看到,按照根搜索算法,所有从root对象可达的对象就被标记为了存活的对象,此
时已经完成了第一阶段标记。接下来,就要执行第二阶段清除了,那么清除完以后,剩下的对象以及对象的状态如下图所示。
可以看到,没有被标记的对象将会回收清除掉,而被标记的对象将会留下,并且会将标
记位重新归0。接下来就不用说了,唤醒停止的程序线程,让程序继续运行即可。
2.2、优缺点
可以看出标记清除法解决了,引用计数法的循环引用问题,没有从root节点引用的对象都会被回收。
缺点:
  • 效率较低,标记和清除两个动作都需要遍历所有对象,并且在GC时,都需要暂停应用程序,对于交互性比较要求比较高的应用而言这种体验非常差
  • 通过标记清除法清理出来的内存碎片化较为严重,因为被清理的对象存在于内存的各个角落,所以清理出来的内存不是连贯的。

3、标记压缩算法
标记压缩算法是在标记清除法的基础上进行了优化,标记阶段是一样的,在清理阶段不是直接清理标记对象,而是将存活对象压缩到内存的一端,然后清理边界以外的垃圾,从而解决碎片化问题。
3.1、原理
3.2、优缺点
解决了标记清除法碎片化问题,同时多了压缩这一步,对象移动内存位置的步骤,其效率有一定的影响。

4、复制算法
复制算法的核心就是,将原有的内存空间一分为二,每次只使用其中一块,在垃圾回收时将正在使用的对象复制到另外一个内存空间中,然后将该内存空间清空,交换两个内存角色完成垃圾回收。
如果内存中的垃圾对象较多,需要复制的对象少,这种情况下使用这个算法比较合适效率较高,反之,不合适。
4.1、JVM中年轻带内存空间
  • 在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。
  • 紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。
  • 经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。
  • GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。

4.2、优缺点
优点:
  • 在垃圾对象多的情况下,效率较高
  • 清理后内存无碎片

缺点:
  • 在垃圾对象少的情况下,不适用,如:老年代内存
  • 内存空间一分为二,只使用其中一个,内存使用率低

5、分代算法
前面介绍了多种回收算法,每一种算法都有自己的优点也有缺点,谁都不能替代谁,所以根据垃圾回收对象的特点进行选择,才是明智的选择。分代算法其实就是这样的,根据回收对象的特点进行选择,在jvm中,年轻代适合使用复制算法,老年代适合使用标记清除或标记压缩算法






0 个回复

您需要登录后才可以回帖 登录 | 加入黑马