GC标记回收

本文介绍了Java中的垃圾回收(GC)机制,包括其目的、标记方式(引用计数和可达性分析),并详细解释了GC的二次标记过程。此外,文章还讨论了Object类中的finalize()方法如何用于对象回收前的操作。

1.什么是GC

Garbage Collection简称为GC,是垃圾回收的意思、内存处理器是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃。Java语言提供的GC功能可以自动的检测对象是否超过作用域,从而达到自动回收内存的目的,java语言没有提供释放已分配内存的显示操作方法,资源回收工作全部交由GC来完成,程序员不能精确的控制垃圾回收的时机。

2.GC的标记

GC在java语言起到资源回收的作用,那么它是如何做到的呢?其实GC是通过一定的算法对需要回收的对象进行标记,符合条件的则进行资源回收。GC的标记方式主要有“引用计数”和“可达性分析”这两种。
(1)引用计数标记
引用计数标记实现起来比较简单,就是给对象添加一个引用计数器,每当有一个地方引用它时就加1,引用失效时就减1,当计数器为0的时候就标记为可回收。这种判断效率很高,但是很多主流的虚拟机并没有采用这种方法,因为其存在很大的局限性,因为它很难解决几个对象之间循环引用的问题,而往往在业务功能的实现需要多个对象的协同,像如下代码中的两个对象的相互引用会导致计数器不会变0即不会回收的情况

public class GCTest {

    private Object o;

    public void test(){

        GCTest g1 = new GCTest();
        GCTest g2 = new GCTest();

        //相互引用
        g1.o = g2;
        g2.o = g1;
    }
}

(2)可达性分析标记
可达性分析标记的设计思路为:将一些可称为“GC Roots”的对象作为起始点,从这些节点开始搜索,搜索和该节点发生直接或者间接引用关系的对象,将这些对象以链的形式组合起来,形成一张“关系网”,又被称为引用链。最后垃圾收集器回收那些不在这张关系网上的对象。如下图:
这里写图片描述

连接GC Roots对象的object是确定还存活的对象,而下边的die Object虽然有引用关系,但是没有和GCROOTS有直接或间接的关系,所以会标记为可回收的对象。目前主流的商用虚拟机用的都是类似的方法,什么对象才能作为“GC Roots”呢?在java中,有四种对象可以作为“GC Roots”

1:栈帧中的引用对象。(栈中的)
2:静态属性引用的对象。(方法区中的)
3:常量引用的对象。(方法区中的)
4:本地方法栈中JNI引用的对象。(本地方法(Native)栈中的)

3.GC的二次标记

Object类有一个finalize()方法,所有类都继承了Object类,因此都会默认实现了这个方法。这个方法的用途是:在该对象被回收之前,该对象的finalize()方法会被调用。这里的回收之前指的就是被标记之后,但是会存在一种情况就是原本一个对象不在上面所讲的“关系网”(引用链)中,但是当开发者重写了finalize()后,并且将该对象重新加入到了“关系网”中,也就是说该对象在系统中还有用,不应该被回收,但是已经被标记了。针对这种情况,虚拟机的做法是进行两次标记,即第一次标记不在“关系网”中的对象。第二次的话就要先判断该对象有没有实现finalize()方法了,如果没有实现就直接判断该对象可回收;如果实现了就会先放在一个队列中,并由虚拟机建立的一个低优先级的线程去执行它,随后就会进行第二次的小规模标记,在这次被标记的对象就会真正的被回收了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值