“要回收的对象”是指那些不可能再被任何途径使用的对象。那么如何找到这些对象?主要有两个算法:
- 给对象中添加一个引用计数器,每当一个地方引用这个对象时,计数器值+1;当引用失效时,计数器值-1。任何时刻计数值为0的对象就是不可能再被使用的。
- 这种算法使用场景很多,不过Java中使用这种算法,因为这种算法很难解决对象之间循环引用的情况。
- 一系列称为“GC Roots”的对象作为起始点,从这些节点向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链(即GC Roots到对象不可达)时,则证明此对象是不可用的。
- GCRoots的对象包括下面几种:(1). 虚拟机栈中引用的对象。(2). 方法区中的类静态属性和常量引用的对象。(3). 本地方法栈中JNI(Native方法)引用的对象。
- 标记可达对象,寻找未标记的对象并释放内存。一般单线程工作并需要停止其他操作。
- 缺点:没有对标记对象进行压缩,导致产生大量碎片,浪费内存。
- 第一阶段和标记清除相同,第二阶段把标记的对象复制到堆栈新域中以便压缩。
- 缺点:这种收集方法也需要停止其他的操作。
- 收集器将堆栈空间分为两个域,每次仅用一半空间。 JVM生成的对象放在一半的空间中,GC运行时把可达对象复制到另一半,从而压缩堆栈。
- 特点:该方法适用短生存期的对象,指定大小堆来说每次都需要两倍大小内存,浪费了内存。
- 把堆栈分为多个域,每次从一个域中收集垃圾。
- 优点:造成较小的应用程序中断时间(STW),使用户一半不能察觉到垃圾收集器正在工作。
- 把堆栈分为2个或者多个域,存放不同寿命的对象-年轻代和老年代
- 不同的代使用不同的算法:
- 年轻代:使用复制算法因为每次GC大批对象死去、少量对象存活.
- 老年代:使用标记清除或者标记压缩,因为对象存活率高、没有额外空间进行分配担保