Java垃圾回收-常见面试题

Object的finalize()方法的作用是否与C++的析构函数作用相同

在这里插入图片描述

public class Finalization {
    private static Finalization finalization;
    /**finalize在gc回收中有不确定性,所以不推荐用finalize进行回收*/
    @Override
    protected void finalize(){
        System.out.println("finalized");
        //System.gc()时,这一步可能没有被执行到就终止了,所以可能为null或对象地址。
        //可以让线程睡眠执行此步骤
        finalization=this;
    }

    public static void main(String[] args) {
        Finalization f = new Finalization();
        System.out.println("first print: "+f);
        f= null;
        //调用Finalization的finalize方法
        System.gc();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("second print: "+f);
        System.out.println(finalization);
    }
}

未加入线程休眠的代码,发现finalization可能输出为null

first print: com.gclhaha.javabasic.jvm.gc.Finalization@1b6d3586
second print: null
finalized
null

加入休眠代码后

first print: com.gclhaha.javabasic.jvm.gc.Finalization@1b6d3586
finalized
second print: null
com.gclhaha.javabasic.jvm.gc.Finalization@1b6d3586

Java中强引用、软引用、弱引用、虚引用有什么用

强引用

在这里插入图片描述

软引用

在这里插入图片描述
软引用还可以配合引用队列去使用

弱引用

在这里插入图片描述
弱引用还可以配合引用队列去使用

虚引用

在这里插入图片描述
gc在回收对象时,这个对象具有虚引用,那么在回收前,回将虚引用加入引用队列中,通过判断引用队列中是否加入虚引用来了解被引用的对象是否被gc回收,可以起到哨兵的作用。

软引用和弱引用也可以先像上面这样配合ReferenceQueue使用。

总结

在这里插入图片描述
在这里插入图片描述

引用队列(ReferenceQueue)

public class ReferenceQueue<T> {

    static private class Lock { };
    private Lock lock = new Lock();
    private volatile Reference<? extends T> head = null;
    private long queueLength = 0;

由上面可以看到ReferenceQueue中只存储了一个head属性,进入Reference看一下

public abstract class Reference<T> {
    private T referent;         /* Treated specially by GC */

    volatile ReferenceQueue<? super T> queue;

    /* When active:   NULL
     *     pending:   this
     *    Enqueued:   next reference in queue (or this if last)
     *    Inactive:   this
     */
    @SuppressWarnings("rawtypes")
    volatile Reference next;


其中,referent保留了创建对象的引用,next指向queue的下一个节点。
在这里插入图片描述
ReferenceQueue通过pollenqueue remove来操作队列

Demo

NormalObject
重写finalize方法

public class NormalObject {
    String name;
    NormalObject(String name){
        this.name = name;
    }
    @Override
    protected void finalize(){
        System.out.println("finalizing NormalObject: "+name);
    }
}

**NormalObjectWeakReference **
重写finalize方法,创建构造方法

public class NormalObjectWeakReference extends WeakReference<NormalObject> {
    String name;
    NormalObjectWeakReference(NormalObject normalObject, ReferenceQueue<NormalObject> referenceQueue){
        super(normalObject,referenceQueue);
        this.name = normalObject.name;
    }
    @Override
    protected void finalize(){
        System.out.println("finalizing NormalObjectWeakReference: "+name);
    }
}

ReferenceQueueTest

public class ReferenceQueueTest {
    private static ReferenceQueue<NormalObject> rq = new ReferenceQueue<>();
    private static void checkQueue(){
        Reference<NormalObject> ref;
        while ((ref = (Reference<NormalObject>)rq.poll()) != null){
            if (ref != null){
                System.out.println("in queue :"+((NormalObjectWeakReference)(ref)).name);
                System.out.println("ref object: "+ref.get());
            }
        }
    }

    public static void main(String[] args) {
        ArrayList<WeakReference<NormalObject>> weakList = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            weakList.add(new NormalObjectWeakReference(new NormalObject("weak"+i),rq));
            System.out.println(weakList.get(i));
        }
        System.out.println("first time");
        checkQueue();
        System.gc();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("second time");
        checkQueue();
    }
}

分析一下,调用主方法,在weakList中添加三个NormalObjectWeakReference对象,打印三个对象的地址。输出first time,调用checkqueue(),没有输出in queue,代表着三个对象并没有被添加到referenceQueue,调用gc()NormalObjectfinalize()输出finalizing NormalObject: weak1/2/3,输出second time,再调用checkqueue(),这时队列不为空,输出内容,ref此时为null
打印结果

com.gclhaha.javabasic.jvm.gc.NormalObjectWeakReference@7f31245a
com.gclhaha.javabasic.jvm.gc.NormalObjectWeakReference@6d6f6e28
com.gclhaha.javabasic.jvm.gc.NormalObjectWeakReference@135fbaa4
first time
finalizing NormalObjec
finalizing NormalObject: weak1
finalizing NormalObject: weak0
second time
in queue :weak0
ref object: null
in queue :weak2
ref object: null
in queue :weak1
ref object: null
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值