1.标记-清除算法
最基础的收集算法。
分为两个阶段:标记出所有需要回收的对象,标记完成后统一回收所有被标记的对象。
不足:效率,空间,标记清除后会产生大量不连续的内存碎片。
不足:1. 效率问题,标记和请求两个操作效率都不高;2.空间问题,会产生大量不连续的空间碎片。
2.复制算法
解决效率问题。
将可用的内存按容量分为大小相等的两块,每次只使用一块。当一块用完了,将还存活的对象复制到另一块,然后再把已使用过的内存空间一次清理掉。
不足:在对象存活率很高的时,要进行较多的复制操作,效率会比较低。
新生代内存分为一块较大的Eden空间和两个较小的Survivor空间,每次使用Eden和其中一块Survivor。当回收时,将Eden和Survivor中还存活的对象一次性的复制到另外一块Survivor空间,最后清理调Eden和用过的Survivor空间。
内存分配担保:如果另一块Survivor空间没有足够空间存放新生代存活下来的对象时,这些对象将直接通过分配担保机制进入老年代。
3.标记-整理算法
复制算法有较多复制操作,效率问题。
根据老年代的特点,标记过程与标记-清除算法一样,后续操作让所有存活对象都像一端移动,然后直接清理掉边界以外的内存。
4.分代收集算法
在新生代中有大批对象死去,少量存活:复制算法。复制成本少。
老年代中对象存活率高,没有额外的空间对他进行担保:就必须使用 标记-清理 或 标记-整理 算法回收。
对象以死吗
一共有两种算法,
引用计数算法,每当有一个地方引用它,计数器值就+1,当引用失效时,计数器值-1,计数器值为0的对象就是不可能在使用的。当对象之间互相引用的时候,计数器值不会为0,就永远不会回收。
GC ROOTS可达性分析算法,GC ROOTS作为起点,从这个节点向下搜索,搜索所有走过的路径称为引用链,当一个对象到GC ROOTS没有任何引用链相连时,就是GC ROOTS对这个对象不可达,则证明这个对象不可用。
可以作为GC ROOTS的对象有以下四种:
虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地变量栈中JNI(一般说的Native方法)引用的对象
引用
引用分为强引用、软引用、弱引用、虚引用。
强引用:指在车光绪代码中最普遍的存在Object obj = new Object()
,这类引用,只要强引用存在,垃圾收集器就不会回收。
软引用:用来描述一些还有用但非必须的对象。SoftReference<Object> softRef=new SoftReference<Object>(obj);
,在系统要发生内存溢出异常之前,将会把这些对象列进回收范围之中,进行第二次回收。如果这次回收还没有足够内存,才会抛出内存溢出异常。
弱引用:也是描述非必需对象的,强度比软引用更弱,弱引用关联的对象只能生存到下一次垃圾收集发生之前,当垃圾收集器工作室时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。WeakReference<Object> weakRef = new WeakReference<Object> (obj)
虚引用:被称为幽灵引用或者幻影引用,是最弱的引用。