JVM GC是:JVM的垃圾回收算法,如今的JVM基本采用分代收集,Young区收集频繁,Old区收集较少,Perm(永久代)基本不回收;JVM进行GC时大部分是对新生代的回收,少许的全局回收。html
GC按照做用的区域分为:算法
Minor GC:做用于新生代数据结构
Major GC(Full GC):做用于老年代,偶尔也会回收老年代和永久代。spa
一、引用计数法线程
引用计数算法很简单,它其实是经过在对象头中分配一个空间来保存该对象被引用的次数。若是该对象被其它对象引用,则它的引用计数加一,若是删除对该对象的引用,那么它的引用计数就减一,当该对象的引用计数为0时,那么该对象就会被标记为垃圾对象。指针
第10行 str引用了“ABC” 则“ABC”的计算器等于1。第11行str释放了该引用,因此“ABC”的计数器就减一。
优势:实现简单,断定高效,能够很好解决大部分场景的问题。
缺点:orm
二、可达性分析法(根搜索算法)htm
可达性分析法:经过一系列"GC Roots"对象做为起始点,开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,认为该对象不可达,则证实该对象是不可用的;
优势:对象
缺点:blog
哪些对象能够做为GC ROOT对象(GCRoot 能够是一个也能够是多个):
一、标记-复制:它将可用内存容量划分为大小相等的两块,每次只使用其中的一块。当这一块用完以后,就将还存活的对象复制到另一块上面,而后在把已使用过的内存空间一次理掉。
JVM实现原理:Survivor区,一块叫From,一块叫To,对象存在Eden和From块。当进行GC时,Eden存活的对象全移到To块,而From中,存活的对象按年龄值肯定去向,当达到必定值(年龄阈值,经过-XX:MaxTenuringThreshold可设置,默认=15)的对象会移到年老代中,没有达到值的复制到To区,而后直接清空Eden和From。以后,From和To交换角色,新的From即为原来的To块,新的To块即为原来的From块,且新的Form块中对象年龄加1.
优势:内存分配时也不用考虑内存碎片等问题;实现简单,运行高效;能够利用指针碰撞(bump-the-pointer)实现快速内存分配
缺点:
应用场景:
二、标记-清除:首先标记出须要回收的对象,标记完成以后统一清除对象。
标记:从根集合开始扫描,标记存货的对象
清除:扫描整个堆内存空间,回收未被标记的对象,使用free-list记录可使用的区域
优势:基于最基础的可达性分析算法,它是最基础的收集算法;然后续的收集算法都是基于这种思路并对其不足进行改进获得的;
缺点:
应用场景:针对老年代
三、标记-整理
标记-整理:标记操做和“标记-清理”算法一致,后续操做不仅是直接清理对象,而是在清理无用对象前,先将存活的对象都向一端移动,并更新引用其对象的指针,而后直接清理掉端边界之外的内存。
标记:和“标记-清理”算法一致
整理:扫描整个堆内存空间,将存活的对象都向一端移动,并更新引用其对象的指针,而后直接清理掉边界之外的内存。整理的目的就是整合零散分布的空间碎片为一个连续的空间。
优势:
缺点:主要是效率问题:除像标记-清除算法的标记过程外,还多了须要整理的过程,效率更低;
应用场景:回收老年代;
四、标记-清除-整理(Mark-Sweep-Compact)
该算法是标记清除和标记整理的结合,标记-清除会产生碎片,标记-整理每次都进行整理效率不高;标记-清楚-整理 是若是老年代内存中没有一块连续续的空间能够存放将要进入对象,就进行整理;若是内存中的空间能够存放将要进入的对象,就进行标记-清除,这样就节省了整理的步骤能够提升效率。总结一句话:不是全部的时候都须要整理的,由于整理也付出代价。主要应用于老年代
总结: 没有最好的算法,只有最合适的引用场景
下一节:GC算法的实现