GC基础

GC

  • 1960年,Lisp使用GC
  • Java中,GC的对象是堆空间和永久区

GC算法

引用计数法(没有被Java采用)

  • 为每个对象标记引用数量,引用数量为0时进行空间释放。

引用和去引用伴随加法和减法,影响性能;
很难处理循环引用。

标记清除(Java老年代)

  • 标记清除算法是现代垃圾回收算法的基础。分为标记和清除两个阶段。
  • 在标记阶段,通过根节点标记所有从根节点开始的可达对象。未被标记的对象时未被引用的垃圾对象。然后再清除阶段清除所有未被标记的对象。

标记压缩(Java老年代)

  • 适用于存活对象比较多的场合,如老年代。
  • 标记压缩算法也是在标记阶段,从根节点开始的可达对象。但之后,它并不简单的清理未标记对象,而是将所有存活对象压缩到内存的一端,之后,清理边界外所有的空间。

复制算法(Java新生代)

  • 与标记清除算法相比,复制算法是一种相对高效的回收方法。
  • 不适合存活对象较多的场合,如老年代。
  • 将原有的内存空间分成两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色。

两块空间完全相同,每次只用一块;
空间浪费问题。

分代思想

  • 根据对象存活周期进行分类,短命对象归为新生代,长命对象归为老年代。
  • 根据不同代的特点,选择不同的算法
    少量对象存活,适合复制算法;
    大量对象存活,适合标记清理或标记压缩算法。

可触及性

  • 可触及对象
    根节点的引用链可以触及到的对象。
  • 可复活的
    一旦所有引用被释放,就是可复活状态,在finalize()中可能复活该对象。
  • 不可触及的
    在finalize()之后,可能会进入不可触及状态,进入该状态后不可被复活,可以被回收。
package cn.chen.gc;

public class CanReliveObj {

    public static CanReliveObj obj;

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("CanReliveObj finalize called");
        obj = this;
    }

    @Override
    public String toString() {
        return super.toString();
    }
}

class Main{
    public static void main(String[] args) throws InterruptedException {
        CanReliveObj.obj = new CanReliveObj();
        CanReliveObj.obj = null;
        System.gc();
        Thread.sleep(1000);
        if(CanReliveObj.obj == null)
            System.out.println("obj是null");
        else
            System.out.println("obj可用");
        System.out.println("第二次gc");
        CanReliveObj.obj = null;
        System.gc();
        Thread.sleep(1000);
        if(CanReliveObj.obj == null)
            System.out.println("obj是null");
        else
            System.out.println("obj可用");
    }
}
CanReliveObj finalize called
obj可用
第二次gc
obj是null

Process finished with exit code 0

避免使用finlize(),操作不慎可能导致错误;
优先级低,何时被调用不确定(何时发生GC不确定);
释放资源可以用try-catch-finally来代替它。

  1. 在栈中引用的对象是根;
  2. 方法区中静态成员或者常量引用的对象(全局对象);
  3. JNI方法栈中的对象。

Stop-The-World

  • Java中的一种全局暂停现象。
  • 全局暂停,所有Java代码停止,native方法可以执行,但不能与JVM交互。
  • Dump线程、死锁检查、堆Dump也可能会导致STW(多半由GC引起)。

猜你喜欢

转载自blog.csdn.net/chen45682kang/article/details/81188027
今日推荐