Java中的四种引用类型

Java中包含一下四种引用类型

   1. 强引用 2. 软引用 3. 弱引用 4. 虚引用


1、强引用

  就是普通的引用,例如: Object o = new Object(),此时 o就是强引用,在这种情况下,即使内存空间不足,它也不会被gc回收,而是会报OutOfMemoryError的错误,当把 o置为null的时候,这个时候才解除了强引用,才会被gc在合适的时间回收,例子如下:

public class M{
    //该方法已被弃用,只是当作演示
    @Override
    protected void finalize() throws Throwable{
        super.finalize();
        //该方法会在gc回收的时候调用
        System.out.println("finalize");
    }
}

public class NormalReference {
    public static void main(String[] args) {
        //首先new一个对象
        //强引用
        M m = new M();
        //然后把对象设置为空
        //取消 强引用
        m = null;
        //手动调用垃圾回收器回收
        System.gc();//此时控制台就会打印 finalize
        try{
            //调用read方法是为了让main方法发生阻塞
            //防止main方法执行完毕退出,然后看不到打印的东西
            System.in.read();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2、软引用

   软引用就是当内存充足的时候。它不会被垃圾回收器回收,当内存空间不够用的时候,软引用就会被垃圾回收器回收,你要理解软引用SoftReference 是一个对象,该对象里存放着数据

用途: 用来做缓存

例子如下:

public class SoftReference {
    public static void main(String[] args) {
        //此时new一个软对象,该对象放一个10M的byte的数组
        SoftReference<byte[]> sf = new SoftReference<>(new byte[1024*1024*10]);
        //此时是可以从sf中拿到数据的
        System.out.println(sf.get());// [B@66133adc
         //手动调用垃圾回收器回收
        System.gc();
        try{
            //睡500毫秒
           Thread.sleep(500);
        } catch (Exception e) {
            e.printStackTrace();
        }
         //此时也是可以从sf中拿到数据的
        System.out.println(sf.get());// [B@66133adc
          //这时,我们再new一个软对象,该对象放一个10M的byte的数组
        SoftReference<byte[]> sf1 = new SoftReference<>(new byte[1024*1024*10]);
         //这个时候,我我们就拿不到数据了,
         //sf就会被垃圾回收器回收了,打印的就是为空
        System.out.println(sf.get());// null
    }
}

注意在运行的时候,需要如下设置

Java中的四种引用类型_第1张图片

3、弱引用

  弱引用就是不管内存中是否有空间,只要遇到垃圾回收器,就会被回收。
用途: 是为了解决某些地方的内存泄露的问题。用在 ThreadLocal里面
  弱引用例子如下:

public class WeakReference {
    public static void main(String[] args) {
        //new 一个弱引用,然后里面存放1M的byte数组
        WeakReference<byte[]> wr = new WeakReference<>(new byte[1024 * 1024);
        //此时在 wr 中是有数据的
        System.out.println(wr.get());
        //手动调用垃圾回收器
        System.gc();
         //这个时候在 wr 中是空的。
        System.out.println(wr.get());
    }
}
4、虚引用

  虚引用会跟一个引用队列相关联使用,它的原理就是,当一个虚引用指向的对象被回收的时候,它会把一个信息添加到跟这个虚引用相关联的这个队列中。还有就是虚引用的get方法,返回的永远是 null

用途: 管理堆外内存 netty NIO

  例子如下:

public class WeakReference {
    private static final List<Object> list = new LinkedList<>();
    //引用队列,跟虚引用相关联
    private static final ReferenceQueue<M> queue = new ReferenceQueue<>();
    public static void main(String[] args) {
        //生成一个虚引用,用来指向M,并且与 queue队列进行绑定
        PhantomReference<M> pr = new PhantomReference<>(new M(), queue);
        //开启一个线程,不断的增加内存
        new Thread(()->{
            while (true) {
                try {
                    //不断的给list添加数据,使内存被占光,
                    //导致虚引用被回收
                    list.add(new byte[1024 * 1024])
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                //打印pr里面的值 ,这里是永远拿不到里面的值的
                System.out.println(pr.get());
            }
        }).start();
        //开启另一个线程,不断的从queue中去数据
         new Thread(()->{
            while (true) {
                try {
                    Reference<? extends M> poll = queue.poll();
                    //当取出来的数据不为空的时候,说明
                    //虚引用指向的对象被回收了
                    if(poll != null) {
                        System.out.println("虚引用指向的对象被jvm回收了");
                    }
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }).start();
        
    }

你可能感兴趣的:(java,Java,4种引用类型)