JVM的五种引用方式

1、强引用

  • 只有GC root对象都不通过[强引用]引用该对象时,该对象才可以被垃圾回收。
    2、软引用
  • 仅有软引用引用该对象时(没有强引用引用该对象),在垃圾回收后,内存依然不足的情况下,会再次触发垃圾回收,此时会回收软引用引用的对象。
  • 可以配合引用队列来释放引用本身
public class TestPerson {
    public static final  int _4MB  = 4 * 1024*1024;
    public static void main(String[] args) {
//        for(int i = 0; i < 5; i++) {
//            list.add(new byte[_4MB]);
//        }
		//list时一个强引用,其引用一个ArrayList对象
        List<SoftReference<byte[]>> list = new ArrayList<>();
        for(int i = 0; i < 5; i++) {
        //soft是一个强引用,引用 SoftReference对象,SoftReference对象软引用一个byte数组对象,即soft相当于通过一个软引用对象引用byte数组
            SoftReference<byte[]> soft = new SoftReference<>(new byte[_4MB]);
            list.add(soft);
            System.out.println(soft.get());
            System.out.println(list.size());
        }
        for(SoftReference<byte[]> b: list) {
            System.out.println(b.get());
        }

    }
}

注释掉的代码执行后会出现内存溢出错误,而通过软引用的的list数组在循环五次后不会出现内存溢出的现象,但是前四个byte数组对象将会被回收掉。
引用队列的作用就是在软引用的对象byte数组被回收后,soft引用的一个SoftReference对象被回收掉。
配合引用队列使用。

public class TestPerson {
    public static final  int _4MB  = 4 * 1024*1024;
    public static void main(String[] args) throws InterruptedException {
//        for(int i = 0; i < 5; i++) {
//            list.add(new byte[_4MB]);
//        }
        List<SoftReference<byte[]>> list = new ArrayList<>();
        ReferenceQueue<byte[]> queue = new ReferenceQueue<>();
        for(int i = 0; i < 5; i++) {
            SoftReference<byte[]> soft = new SoftReference<>(new byte[_4MB],queue);
            list.add(soft);
            System.out.println(soft.get());
            System.out.println(list.size());
        }
        Reference<? extends byte[]> poll = queue.poll();
        while (poll != null) {
            list.remove(poll);
            poll = queue.poll();
        }
        System.out.println("=============");
        for(SoftReference<byte[]> b: list) {
            System.out.println(b.get());
        }

    }
}

3、弱引用

  • 仅有弱引用该对象时,在进行垃圾回收时,无论内存是否充足,该对象都会被回收掉。
  • 如果只是小范围的垃圾回收,没有触发Full gc的情况下,部分弱引用不会被回收,但是如果触发一次 full gc时,弱引用对象都会被回收。
public class TestPerson {
    public static final  int _4MB  = 4 * 1024*1024;
    public static void main(String[] args) throws InterruptedException {
       List<WeakReference<byte[]>> list =  new ArrayList<>();
       for(int i = 0; i < 5; i++) {
           list.add(new WeakReference<byte[]>(new byte[_4MB]));
       }
       System.gc();
       for (WeakReference<byte[]> b :list) {
           System.out.println(b.get());
       }

    }
}

有System.gc()和没有输出时两种不同的结果。

  • 可以配合引用队列释放引用本身。
    4、虚引用
    必须配合引用队列使用,主要配合byteBuffer使用,被引用对象回收时,会将虚引用入队,由Reference Handler线程调用虚引用对象相关方法释放直接内存。
    5、终结器引用
  • 无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有
    被回收),再由 Finalizer线程通过终结器引用找到被引用对象并调用它的finalize方法,第二次GC时
    才能回收被引用对象
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值