本次只是介绍几种算法的思想和发展过程
简单分为了
1.标记-清除算法
2.复制算法
3.标记-整理算法
4.分代收集算法
1.标记-清除算法
分为了标记和清除两个过程,首先标记出需要回收的对象,然后标记完成统一进行回收
基于这个思想发展了出了多个收集算法,但是其具有不足之处,一个是效率问题,标记和清除两个过程中的效率都不太高,
另外就是空间上的问题,在标记清除后会产生大量的不连续内存碎片,内存碎片过多会导致后来的程序在运行过程中因为找不到合适的内存,触发一次GC动作
2.复制算法
将可用的内存按照容量分为两个大小相等的区域,每次只使用其中一个,当一个内存用完了,就将存活的对象复制到另一块中,再将已经使用过的内存空间进行全清理,这样是效率高,而且按照顺序进行分配内存,实现简单,但是这种算法的代价是将内存缩小为了原来的一半,代价较高
现在主流的虚拟机都是采用的如此的算法,将一个内存分为了
两个较小的Survivor空间和一个较大的Eden空间,每次使用一个Survior和Eden.当回收是,将Eden和Surivor中存活对象一次性的复制到另一块Survivor空间上,然后清理掉Eden和刚刚使用的Survivor空间,默认使用比例是8:1:1
这样对于浪费,也是浪费1/10
在回收完成的对象无法被一个Survivor空间保存的时候,会触发诸如分配担保的情况
3.复制收集算法
因为会进行复制操作,而且会浪费空间,所以就有人提出了标记-整理算法
其和标记-清除算法不一致的为,后续过程不是直接进行清理,而是让所有存活的对象都向着一遍去移动,然后清除边界外内存.
4.分代收集
在现代来说,单纯使用单一算法来面对虚拟机中复杂的内存使用情况是不合算的
一般会根据对象存活周期将内存分为几块,常见的是将Java堆分为新生代和老年代,然后根据年代特点采用合适的收集算法
如果只有少量存活,就采用复制算法,而在老年代中,因为存活率高,且没有额外空间
必须使用标记-清理和标记-整理算法来进行处理