java的4种引用类型

原创文章:java的4种引用类型 – 编程屋

目录

1 前言

2  4种引用类型

2.1 强引用

2.2 软引用

2.3 虚引用

2.4 弱引用


1 前言

java中的4种引用类型,强引用软引用弱引用虚引用。说这4种引用之前,需要先说一下垃圾回收机制中的finalize()方法,

finalize()方法是Object中的方法,它只有一个空的方法体,并且被protected修饰:

 当一个java对象被当成垃圾回收的时候,垃圾回收器会负责调用finalize()方法。

2  4种引用类型

2.1 强引用

强引用:一般来讲就是直接被new出来的对象(Object o = new Object();),只要强引用存在,垃圾回收器就不会回收被引用的对象。

为了证明上述结论,可以做以下验证。

1)重写finalize()方法,因为Object中的finalize()方法只有一个空的方法体,不方便进行测试。

public class Person {

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize");
    }
}

2)测试方法进行测试

    public static void main(String[] args) throws IOException {
        Person person = new Person();
  
        System.gc();//触发垃圾回收
        System.out.println(person);
        System.in.read();//阻塞main线程,给垃圾回收线程执行
    }

解析:创建一个Person对象,此时是一个强引用,即便是触发了垃圾回收,垃圾回收器也不会回收被引用的对象。

结果输出了person对象地址,并没有输出finalize()方法体中语句。

 那如果将该强引用删掉呢(将person置为null就行)

    public static void main(String[] args) throws IOException {
        Person person = new Person();
        person = null;
        System.gc();//触发垃圾回收
        System.out.println("person:"+person);
        System.in.read();//阻塞main线程,给垃圾回收线程执行
    }

再次执行,发现该对象被回收掉。

2.2 软引用

软引用:如果一个对象只具有软引用,并且当前虚拟机的内存足够,那么它就不会被垃圾回收器回收,否则就会回收软引用对象。

    public static void main(String[] args) {
        SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 10]);
        System.out.println("softReference:"+softReference.get());
        System.gc();
        try { //进行睡眠让垃圾回收有时间执行
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("softReference:"+softReference.get());

    }

分析下以上代码:

SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 10]);

 创建了一个10m大小的byte对象,放到了软引用对象中,并且有一个softReference对象指向了软引用对象。如下:

 为了证明上述所说情况在内存足够的情况下运行。控制台输出如下:

 可以发现软引用对象并没有被垃圾回收。但是如果将虚拟机内存最大设置为20M,并且再创建一个10M的字节数组,它还会这样不会被回收吗?

 再次创建一个字节数组。

    public static void main(String[] args) {
        SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 10]);
        System.out.println("softReference:"+softReference.get());
        System.gc();
        try { //进行睡眠让垃圾回收有时间执行
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("softReference:"+softReference.get());

        byte[] bytes = new byte[1024 * 1024 * 10];
        System.out.println("softReference:"+softReference.get());

    }

控制台输出:

可以发现此时,软引用对象已经被回收。

由此可以证明如果一个对象只具有软引用,并且当前虚拟机的内存足够,那么它就不会被垃圾回收器回收,否则就会回收软引用对象。

通常软引用用作缓存处理,先从软引用中获取,如果没有获取到,再从缓存中获取。

2.3 虚引用

虚引用:虚引用必须与引用队列(ReferenceQueue)一起使用,当垃圾回收器准备回收一个对象时,如果发现它有虚引用,就会把这个虚引用加入到与之相关联的队列中,然后就可以通过监听引用队列得知虚引用的回收。

private static final List<Object> LIST = new LinkedList<>();

    private static final ReferenceQueue<Person> QUEUE = new ReferenceQueue<>();

    public static void main(String[] args) {
        PhantomReference<Person> phantomReference = new PhantomReference<>(new Person(), QUEUE);
        System.out.println(phantomReference.get()); //null

        //设置-Xmx20M,向内存中放置大小
        new Thread(()->{
            while (true){
                LIST.add(new byte[1024 * 1024]);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(phantomReference.get());
            }
        }).start();

        new Thread(()->{
            while (true) {
                Reference<? extends Person> poll = QUEUE.poll();
                if (poll != null ) {
                    System.out.println("虚引用对象被jvm回收了======="+poll);
                }
            }
        }).start();

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
public class Person {

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize");
    }
}

 代码解析:

1)全局定义一个LIST集合和一个引用队列QUEUE

2)定义一个虚引用对象phantomReference并将测试回收对象Person以及队列放入其中。

3)将虚拟机大小设置最大为20M

4)设置两个线程,一个线程向内存中不断的添加大小(目的是内存满了之后垃圾回收机制回收Person类并将虚引用放入引用队列QUEUE中)另外一个线程是为了测试是否拿到放入队列中的线程。

控制台输出如下:

 发现结论是正确的。

2.4 弱引用

以上只是部分内容,为了维护方便,本文已迁移到新地址:java的4种引用类型 – 编程屋

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值