一、垃圾回收算法
垃圾回收算法分为垃圾收集算法和垃圾回收算法
1、垃圾收集算法:
1)、引用计数器算法:
有引用计数器+1,引用销毁的时候,计数器-1,当引用计数器=0时,
对象已经没有引用了,可以回收了!
弊端:相互引用形成一个环,则无法回收。
2)、根搜索算法(root节点算法、可达性分析算法)
从一个Root节点开始,寻找引用节点,剩余没有被引用的节点,则为无用节点,可以被回收。
扩展:
JAVA引用分类:
a)、强引用:
创建一个对象并把这个对象赋给一个引用变量,有引用变量指向时永远不会被垃圾回收;
例:Object obj = new Object();
obj对象对后面new Object的一个强引用
b)、软引用:
非必须引用,内存溢出之前进行回收;软引用主要用户实现类似缓存的功能;
例:Object obj = new Object();
SoftReference sf = new SoftReference(obj);
sf是对obj的一个软引用
c)、弱引用:
当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象;
d)、虚引用(幽灵/幻影引用):
每次垃圾回收的时候都会被回,主要用于检测对象是否已经从内存中删除。
每次垃圾回收的时候都会被回,主要用于检测对象是否已经从内存中删除。
2、垃圾回收算法:
1)、标记-清除算法:
从根集合进行扫描,对存活的对象对象标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收
缺点:由于直接回收不存活的对象,会造成内存碎片
2)、复制算法:
从根集合扫描,并将存活对象复制到一块新的,没有使用过的空间中
缺点:需要一块内存交换空间用于进行对象的移动,成本高。
3)、标记-整理算法:
采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,
会将所有的存活对象往左端空闲空间移动,并更新对应的指针;
缺点:造成内存碎片,且成本更高
4)、分代收集算法:
根据对象存活的生命周期将内存划分为若干个不同的区域,一般分为新生代(复制算法)和老年代(标记整理算法)
二、常见的垃圾收集器
1、Serial收集器(复制算法):单线程的收集器。在进行垃圾收集时,必须暂停其他所有的工作线程,直到收集完成。
2、ParNew收集器:Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现。
3、Parallel Scavenge(并行回收)收集器:
新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器。可达到一个可控制的吞吐量。
主要适合在后台运算而不需要太多交互的任务。
4、Serial Old 收集器:Serial收集器的老年代版本,它同样是一个单线程收集器,使用标记整理算法
5、Parallel Old 收集器:是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法
6、CMS收集器:一种以获取最短回收停顿时间为目标的收集器,
步骤:初始标记(需要Stop The World,)、并发标记、重新标记(需要Stop The World,)、并发清除
优点:并发收集,低停顿
缺点:对CPU资源非常敏感;无法处理浮动垃圾;基于“标记-清除”算法实现的收集器,会有大量空间碎片产生
7、G1收集器:是一款面向服务端应用的垃圾收集器,
步骤:初始标记、并发标记、最终标记、筛选回收
优点:并行与并发,分代收集,空间整理 (标记整理算法,复制算法),可预测的停顿。
jdk1.7 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)
jdk1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)
jdk1.9 默认垃圾收集器G1