【JVM】(四) :垃圾回收机制(GC)
垃圾的标准对象被判定为垃圾的标准:
判断对象是否为垃圾的算法:
引用计数算法判断对象的引用数量:
代码示例 public void ReferenceQuoteCounterProblem(){ MyObject object1 = new MyObject(); //(1) count=1 创建对象 MyObject object2=object1; //(2) count=2 object1= null; //(3)count=1 object2=null; //(4) count=0 该对象实例可以被当作垃圾收集 } 如下图所示,每一根指向或剪断堆中的线代表引用计数器+1或-1 ? 优点:执行效率高,程序执行受影响较小 缺点:无法检测出循环引用的情况,导致内存泄漏 代码示例 public void ReferenceQuoteCounterProblem2(){ MyObject object1 = new MyObject(); MyObject object2 = new MyObject(); object1.childNode = object2; object2.childNode = object1; } ? 注:该算法机制在jvm不常用 可达性分析算法通过判断对象的引用链是否可达来决定对象是否可以被回收 ? 可以作为GC Root的对象
回收算法垃圾回收算法
?注:这里只讲最常用的四种回收算法 标记-清除算法(Mark-Sweep)此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。此算法需要暂停整个应用,同时,会产生内存碎片。
如下图所示 ? ?注:该算法缺点明显,由于标记清除不需要对象的移动,因此会造成多个不连续的碎片。空间碎片太多,当存在分配较大的对象内存(占四个格子)时,没有足够的连续内存,而不得不提前触发另一次GC工作(一直保持clean状态), 导致OOM 复制算法(Copying)此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。次算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间。(推倒重建,只需要移动堆顶指针,按顺序分配内容,高效简单)
如下图所示 优点:
标记-整理算法(Compacting)此算法结合了“标记-清除”和“复制”两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象“压缩”到堆的其中一块,按顺序排放。此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。(标记加移动地址造成成本更高)
如下图所示 优点:
分代收集算法(Generational Collector)这种收集器把堆栈分为两个或多个域,用以存放不同寿命的对象。虚拟机生成的新对象一般放在其中的某个域中。过一段时间,继续存在的对象将获得使用期并转入更长寿命的域中。分代收集器对不同的域使用不同的算法以优化性能。这样可以减少复制对象的时间。(这里只演示JDK8中堆)
在Java8及以上版本的虚拟机分代垃圾回收机制中,应用程序可用的堆空间可以分为年轻代与老年代,然后年轻代有被分为Eden区,From区与To区,如下图所示: ? GC分类
年轻代年轻代是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,结束生命,具有有朝生夕死的性质。(尽可能快速地收集掉那些生命周期短的对象)
采用算法
年轻代三次GC回收流程图如下:
对象如何晋升到老年代
常用的调优参数
老年代存放生命周期较长的对象 采用算法
触发Full GC的条件
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |