JVM系列扩展:常见垃圾回收算法
2016-10-16 13:59
387 查看
对象存活算法
在回收垃圾对象之前,垃圾收集器需要确认哪些对象“存活”和那些对象应该被回收引用计数(Reference Counting)
引用计数是最古老的一种算法,在微软的COM组件技术,Adobe的ActionScript3中都有使用。实现就是:对于一个对象A,只要任何一个对象引用了A,则A的引用计数器就加1;当引用失效时,引用计数器就减1;当一个对象的计数器值为0时,则对象A则不可能再被使用。引用计数的缺点在于:
无法处理循环引用的情况,例如A引用了B,B引用了A,但是系统中不存在任何第3个对象引用了A,B(此时A,B应该是要被回收的),但是A,B的计数器都为1,无法被回收。
引用计数器要求每次引用产生或者消除时,都需要做相应的加减运算,会对系统性能产生影响。
可达性分析算法 (Reachability Analysis)
在主流的商用程序语言的主流实现中,都是通过可达性分析来判断一个对象是否应该存活的。其基本思想就是通过一系列的称为“GC Roots”的对象作为根节点,从这些节点开始向下搜索,搜索所走过的路径称为“引用链”。当一个对象到“GC Roots”没有任何的引用链相连时,则证明此对象可以被回收。在Java虚拟机中,可作为GC Roots的对象包括以下几种:
虚拟机栈(栈帧中局部变量表)中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中JNI(即一般说的native方法)引用的对象
扩展:Java语言的四种引用类型:强引用,软引用,弱引用,虚引用
垃圾回收算法
标记清除算法(Mark-Sweep)
标记清除算法将垃圾回收分为标记,
清除两个阶段。在
标记阶段,标记所有从根节点开始的可达对象,此时未标记的对象即为垃圾对象,等待回收。在
清除阶段,清除所有的未标记对象。
标记清除的缺点在于:
回收后的空间容易产生空间碎片
复制算法(Copying)
复制算法的核心思想是将原有的内存空间分为两块,每次只使用其中的一块,在垃圾回收时,将存活的对象复制到另一块未被使用的空间,之后清除原来使用的空间中的所有对象。复制算法的优点:
如果系统的垃圾对象多,复制算法要复制的存货对象就少,因此效率会高
不会产生空间碎片
缺点:
可用内存折半,总是存在一块内存不被使用
在Java虚拟机新生代串行垃圾回收器中,使用了复制算法的思想。新生代被分为
eden,
from,
to三个内存空间。其中
from,
to是两块大小相当,地位相同且可进行角色互换的空间,也统称为
survivor空间。
标记压缩算法 (Mark-Compact)
相比于复制算法存活对象少,垃圾对象多的情况,标记压缩算法通常用于大部分对象都是存活对象的情况(老年代的回收算法)。它在标记清除算法的基础上做了一些优化,在标记存活对象后,将所有的对象压缩到内存的一端,然后再清除边界外的所有空间。
优点:
避免产生碎片
内存使用率高,不存在内存折半的现象
因为只是比
标记清除多了一个压缩的步骤,所以也被称为
标记清除压缩算法(MarkSweepCompact)
分代算法 (Generational Collecting)
在上面的一系列算法中,并没有哪种算法可以完全的替代其他的算法。它们各自具备自己独特的优势和特点。因此,将内存区间根据对象的特点分成几块,每块使用不同的回收算法,以提高垃圾回收效率,这就是分代算法。在Java虚拟机中,所有的新建对象都会优先存放在
新生代内存空间中,对于新生代内存空间中的对象,很容易就被回收,因此新生代适合复制算法。当一个对象经过几次回收后仍然存活,该对象就会被放入
老年代内存空间,在老年代内存空间的对象,经过几次垃圾回收后仍然存活的概率通常很大,根据分代的思想,老年代适合标记压缩或标记清除算法。
相关文章推荐
- JVM 垃圾回收机制和常见算法
- JVM系列(一)垃圾回收算法
- 细说JVM系列:自动内存管理内存回收:垃圾收集理论-垃圾收集算法
- JVM常见垃圾回收算法
- JVM系列见解之垃圾回收概念和算法
- JVM常见垃圾回收算法
- JVM调优总结(三)- 基本垃圾回收算法
- JVM 垃圾回收算法
- JVM调优总结(九) -新一代垃圾回收算法
- JVM调优总结(九)-新一代的垃圾回收算法
- JVM 垃圾回收算法介绍
- JVM内存回收算法以及垃圾收集器
- JVM系列六:java6_garbage collection(垃圾回收)
- JVM调优总结(三)-基本垃圾回收算法
- JAVA-JVM垃圾回收算法简介
- JVM学习总结二——垃圾回收算法
- JVM调优总结(三)-基本垃圾回收算法
- JVM 垃圾回收算法
- JVM调优总结(九)-新一代的垃圾回收算法