上篇文章介绍了老年分担机制,在minorGC前会先判断一下老年代剩余空间是否大于需要移动的数据,如果大则直接fullGC,否则会看看是否配置了参数,没有则直接fullGC,有的话再算每次yangGC的平均值,再次比较老年代剩余空间,小于他的话则正常yangGC。
Jvm对象回收算法-JVM(九)
一、垃圾收集的算法
垃圾收集算法有三种,复制算法、标记整理清理和标记清除算法。他们都是基于分代收集的理论来运行的。
1、分代收集理论
根据对象周期不同将内存分成几块,一般分为新生代和老年代,这样我们可以选择各个年龄代特点选择合适的垃圾收集算法。
新生代特点是每次有百分之99的对象死去,所以可以选择复制算法,只需要付出少量复制成本就可以完成垃圾回收。而老年代是经过多轮GC而还存活的,所以存活率高,没有额外空间进行分配,所以选择 标记整理 或者 标记清除。
2、标记-复制算法
复制算法会把内存分成两块,每次使用完其中一块,就将还存活的对象复制到另一块。
用前面说的可达性分析算法,通过GC roots一层层向下标记是否是垃圾对象,内存整理后,会按顺序放入另一块内存。
3、标记-清除算法
老年代用复制算法则会浪费空间,年轻代对象本身就不多,老年代大部分对象都是存活的,所以不适合复制算法。
1)效率问题:如果存活的对象太多,则标记的太多,影响效率。
2)空间问题:标记清楚后会产生大量不连续的碎片。
不连续碎片意味着大对象放进来会存储不了,除非把内存里的对象整理一下,让空闲的内存空间规整到一起。
4、标记-整理算法
前面和标记清除一直,利用可达性分析标记,但是清除完成之后,不会产生连续的碎片,会规整整个内存空间,将对象放在连续的空间。
二、垃圾收集器
年轻代垃圾收集器:Serial、ParNew、Parallel、CMS、Serial Old、Parallel Old。
老年代垃圾收集器:G1、ZGC、Epsilon、Shenandoan
1、Serial收集器
-XX: UseSerialGC -XX: UseSerialOldGC
一个年轻代收集器,一个老年代收集器。
串行是最基本的垃圾收集器,“单线程”收集器,效率比较低,并不仅仅一条线程去垃圾回收,在他收集的时候还会STW,直到他收集结束。
新生代采用复制算法,老年代采用标记整理算法。
2、Parallel Scaenge收集器
-XX: UseParallelGC(年轻代) -XX: UseParallelOldGC(老年代)
他就是serail的多线程版本,线程可以通过-XX:ParallelThreads来配置指定收集线程的线程数,但一般不推荐修改。他的吞吐量更高,高效率利用假期多核CPU。CMS等垃圾收集器则更关注于用户停顿时间,提高用户体验。
在JDK1.8的版本,老年代和年轻代都用的Parallel,对于小内存效率很好。它STW时间长,内存越大时间越长,所以适合内存大。
新生代采用复制算法,老年代采用标记整理算法。
3、ParNew收集器
-XX: UseParNewGC
与Parallel类似,但Parallel不能与cms配合执行,但是ParNew可以。如何配合呢,parNew使用在年轻代,CMS使用在老年代。
新生代采用复制算法,老年代采用标记整理。