1、分代收集算法
新生代:复制收集算法(年轻代特点是内存空间相对老年代较小,对象存活率低。)
复制算法的效率只和当前存活对象大小有关,因而很适用于年轻代的回收。而复制算法的内存利用率不高的问题,可以通过虚拟机中的两个Survivor
区设计得到缓解。
老年代:标记清除+标记整理算法(老年代的特点是内存空间较大,对象存活率高。)
这种情况,存在大量存活率高的对象,复制算法明显变得不合适。一般是由标记清除或者是标记清除与标记整理的混合实现。
次数上频繁收集Young区
次数上较少收集Old区
基本不动元空间
2、GC四大算法
1)引用计数法
2)复制算法(Copying)
年轻代中使用的是Minor GC ,这种GC算法采用的是复制算法()
Minor GC 会把Eden中的所有活的对象都移到Survivor区域中,如果Survivor区中放不下,那么剩下的活的对象就被移到Old generation中,也即一旦收集后,Eden是就变成空的了。
当对象在Eden出生后,在经过一次MinorGC后,如果对象还存活,并且能够被另外一块Survivor区域所容纳,则使用复制算法将这些任然存活的对象复制到另外一块Survivor 区域中,然后清理所使用过的Eden以及Surivor区域,并且将这些对象的年龄设置为1,以后对象在Survivor区没熬过一次MinorGC,就将对象的年龄+1,当对象的年龄到达某个值时(默认是15岁,通过-XX:MaxTenuringThreshold来设定参数),这些对象就会成外老年代
HotSpot JVM把年轻代分为了三个部分:1个Eden区和2个Survivor区(分别叫from和to)。默认比例为8:1:1,一般情况下,新创建的对象都会被分配到Eden区(一些对象特殊处理),这些对象经过第一次Minor GC后,如果任务存活,将会被移动Survivor区。对象在Survivor区中每熬过一次MinorGC,年龄就会增加1岁,当它的年龄增加到一定程度是,就会被移动到老年代中,因为年轻代中的对象基本都是朝生夕死(90%以上),所以在年轻代的垃圾回收算法使用的是复制算法,复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面,复制算法不会产生内存碎片
在GC开始的时候,对象只会存在于Eden区和名为from的Survivor区,Survivor区to是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到to,而在from区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(默认15)的对象会被移动到老年代中,没有达到阈值的对象会被复制到to区域。经过这次GC后,Eden区和from区已经被清空。这个时候,from和to会交换他们的角色,也就是新的to就是上次GC前的from,新的from就是上次GC前的to。不管怎样,都会保证名为to的Survivor区域是空的。Minor GC会一直重复这样的过程,直到to区被填满,to区被填满之后,会将所有对象移动到老年代中
因为Eden
区对象一般存活率较低,一般的,使用两块10%的内存作为空闲和活动区间,而另外80%的内存,则是用来给新建对象分配内存的。一旦发生GC,将10%的from
活动区间与另外80%中存活的Eden
区对象转移到10%的to
空闲区间,接下来,将之前90%的内存全部释放,以此类推。
缺点:
浪费了一半的内存
复制操作耗时(当对象存活率达到一定程度是)
3)标记清除(Mark-Sweep)
老年代一般是由标记清除或者是标记清除与标记整理的混合实现
算法分发标记和清除两个阶段,先标记出要回收的对象,然后同意回收这些对象
用通俗的话解释一下标记清除算法,就是当程序运行期间,若可以使用的内存被耗尽的时候,GC 线程就会被触发并将程序暂停,随后将要回收的对象标记一遍,最终统一回收这些对象,完成标记清理工作接下来便让应用程序恢复运行。
总结就是:
1、标记和清除两个操作,有两次扫描,耗时严重,会产生内存碎片
2、触发这个算法会使得程序暂停,的操作完成以后才能让应用程序恢复运行
4)标记也压缩(Mark-Compact)
1、标记
原理与标记清除一样
2、压缩
再次扫描,并发一端滑动存活对象
总结:
没有内存碎片,可以利用bump
需要移动对象的成本
(1)内存效率: 复制算法 > 标记清除算法 > 标记整理算法(此处的效率只是简单的对比时间复杂度,实际情况不一定如此)。
(2)内存整齐度: 复制算法 = 标记整理算法 > 标记清除算法。
(3)内存利用率: 标记整理算法 = 标记清除算法 > 复制算法。
年轻代:
3、GC算法总体概述
JVM在进行GC时,并非每次都对上面三个内存区域一起回收的,大部分时候回收的都是指新生代。
因此GC按照回收的区域又分为了两种类型,一种是普通GC(minor GC),一种是全局GC(Major GC or Full GC)
普通GC:只针对新生代区域的GC,指发生在新生代的垃圾收集动作,因为大多数Java对象存活率都不高,所有MinorGC 非常频繁,一般回收速度也比较快
全局GC:指发生在老年代的垃圾收集动作,出现了Major GC,经常会伴随至少一次的Minor GC(但不是绝对)。Major GC 的速度一般要比Minor GC慢上10倍以上