垃圾回收原理机制及算法(GC)

Java主要做三件事:

哪些内存需要回收?

什么时候回收?

如何回收?

 

Java中哪些内存需要回收?

jvm会分配一个运行时内存空间。包括五部分:程序计数器,虚拟机栈,本地方法栈,方法区,堆。其中程序计数器,虚拟机栈,本地方法栈是每个线程私有内存空间,随线程而生,随线程而亡。这三个区域的内存分配和回收都是确定的,无需考虑回收问题。

        方法区和堆需要考虑,一个接口的多个实现类需要的内存可能不一样,只有在程序运行期间才知道会创建哪些对象,这部分的内存分配和回收是动态的,GC主要关注的是这部分的内存。涉及到多线程(堆),堆个对象不同类型的引用(方法区),才会涉及GC回收。

小结:Java GC针对的是jvm中堆和方法区。

        

Java GC 机制启动之前,需要确定堆内存中哪些对象是存活的,两个方法:引用计数法和可达性分析法。

        https://blog.****.net/qq_37986734/article/details/87161513

 

Java GC 垃圾回收算法 

  

(一)标记-清除算法

        

分为”标记“和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象,这是最基础的收集算法,后续的收集算法都是基于这种思路并对其不足进行改进而得到的。

不足:标记和清除这两个效率都不高,空间问题,标记清楚之后会产生大量不连续的内存碎片,空间碎片太多可能导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不触发另一次垃圾收集动作。(看下面的图就很好理解了)垃圾回收原理机制及算法(GC)

 

(二)复制算法

       它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活的对象复制到另外一块上去,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆指针,按顺序分配内存即可,实现简单运行高效。只是这种算法的代价是将内存缩小为原来的一半。垃圾回收原理机制及算法(GC)

 

(三)标记-整理算法

        标记过程仍与标记清楚算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象,都向一端移动,然后直接清理掉端边界以外的内存,垃圾回收原理机制及算法(GC)

 

(四)分代收集算法

       当前商业虚拟机的垃圾收集都采用“分代收集”算法,这种算法并没有什么新的思想,只是根据对象的存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存货,那就选用复制算法,只需付出少量存货对象的复制成本就可以完成收集。而老年代中因为对象存货率高,没有额外空间对它进行分配担保,就必须使用“标记-清理“或者”标记-整理“算法进行回收。