讲一讲垃圾回收算法
算法一:引用计数法,这是一种经典的方法,具体是对对象设置一个计数器,每增加一个变量对其的引用,引用计数器就增加1;每减少一个,引用计数器就减少1.只要当引用计数器变为0的时候就会被回收。
劣势:1、采用这种办法无论增加减少都是频繁操作对象,增加系统的损耗。2、这种方法无法处理循环引用的情况,就是A引用B,B中也引用A了。这时候相互引用导致无法回收A与B,导致内存泄露。
算法二:标记清除法。这个方法将其分为两个阶段:标记阶段与清除阶段。标记阶段,通过对象,标记所有跟节点开始的可达对象,那么未标记的对象就是未被引用的垃圾对象。在清除阶段,清除掉所有的未标记的对象。
缺点:这种办法回收会导致大量的内存碎片,因为对象在堆中的内存是固定的,删除后到知道整个空间内,有的使用,有的没使用,不利用java内存管理。
算法三:标记整理法:(JAVA old老年代区使用)算法分为三个节点,标记阶段、压缩阶段、清楚阶段。标记阶段和清除阶段不变,知识增加了一个压缩阶段,就是做完标记后,将标记的对象记录开始与结束的地址整体向左移动集中排列到一起,这样清楚将不会生成磁盘碎片。效率比标记清除低。
缺点:压缩阶段会增加系统的消耗,如果对象很多那么系统的损耗非常大,标记对象少的话,效率比较高。
算法四:复制算法(JAVA 新生代采用) 核心思想就是将内存空间分成两块,同一时刻只是用其中一块,垃圾回收时将正在使用的内存中的存活的对象复制到使用的内存中去,然后清除这一内存块中的所有对象。交替使用这两块内存块,不会产生内存碎片达到垃圾回收的目的。(将堆划分为几个部分,根据堆划分的内存区分不同选择不同的GC策略)
确定:这样会使内存空间对折,利用效率太低。
算法五:分代法(JAVA堆采用)
主要思想根据对象的生命周期长短特点将其进行分块,根据每块内存区域的特点,使用不同的回收算法,从而提高垃圾回收效率。比如内存分代划分 new old,对于不同的代采用不同的垃圾回收算法。其中old使用整理清除,from to使用复制算法。
补充一个小的不常见的:增量算法:主要是这样的如果一次性将所有的垃圾进行处理,需要造成系统的长时间的停顿,那么就可以让垃圾收集线程和应用程序交替执行,每次垃圾收集线程只收集一小片区域的内存空间,接着切换到应用程序线程。依次反复,直到垃圾收集完成。使用这种方式,由于在垃圾回收过程中,间断性地执行了应用程序代码,所以能减少系统的停顿时间,但是能较少系统的停顿时间。但是,因为线程切换和上下文转换的消耗,会是的垃圾回收的总体成本上升,系统的吞吐下降。(所以不推荐使用。。。)
原文:https://blog.csdn.net/weixin_39893439/article/details/81128581