Java的四种引用-强引用,软引用,弱引用,虚引用

1.强引用

强引用是最普遍的一种引用,我们写的代码,99.9999%都是强引用:

2.软引用

软引用就是把对象用SoftReference包裹一下,当我们需要从软引用对象获得包裹的对象,只要get一下就可以了
特点:
当内存不足,会触发JVM的GC,如果GC后,内存还是不足,就会把软引用的包裹的对象给干掉
也就是只有在内存不足,JVM才会回收该对象。

SoftReference<Student> studentSoftReference=new SoftReference<Student>(new Student());
Student student = studentSoftReference.get();
System.out.println(student);
  • 模拟回收软引用
    • 设置堆内存最大20M -Xmx20M
public static void main(String[] args) {
    SoftReference softReference=new SoftReference(new byte[1024 * 1024 * 10]);
    System.out.println(softReference.get());
    System.gc();
    //手动垃圾回收后,发现内存还足够。所以软引用没有被回收
    System.out.println(softReference.get());
      //造成内存不足,进行一次垃圾回收。垃圾回收后内存还是不足。就把软引用的回收了
    byte[] bytes = new byte[1024 * 1024 * 10];
    System.out.println(softReference.get());
}
  • 输出结果
    在这里插入图片描述

3.弱引用

弱引用的使用和软引用类似,只是关键字变成了WeakReference
特点:
弱引用的特点是不管内存是否足够,只要发生GC,都会被回收:

WeakReference<byte[]> weakReference = new WeakReference<byte[]>(new byte[1]);
System.out.println(weakReference.get());
System.gc();
System.out.println(weakReference.get());
  • 输出结果在这里插入图片描述

4.虚引用

虚引用需要和ReferenceQueue配合一起使用(把对象,和队列都放入虚引用中)
当发生GC,虚引用指向的对象会被回收,并且会这个对象关联的虚引用(就是这个reference )放到ReferenceQueue中

作用:
在回收直接内存的时候,靠的就是这个

  • 模拟回收直接内存过程
    • 创建一个低级的线程,一直监听虚引用关联的队列
    • 一但队列有内容了,就根据队列存的入口地址。去执行相关的方法(释放直接内存)
ReferenceQueue queue = new ReferenceQueue();
PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1], queue);
System.out.println(reference.get());

public static void main(String[] args) {

    ReferenceQueue queue = new ReferenceQueue();
    List<byte[]> bytes = new ArrayList<>();
    PhantomReference<Test2> reference = new PhantomReference<Test2>(new Test2(),queue);
    //这个线程,主要是用来造成堆内容溢出,然后进行垃圾回收
    new Thread(() -> {
        for (int i = 0; i < 100;i++ ) {
            bytes.add(new byte[1024 * 1024]);
        }
    }).start();

   //这个线程一直监听虚引用关联的队列,当队列有东西了,说明虚引用的对象被回收了
    new Thread(() -> {
        while (true) {
            //获取队列里面的内容
            Reference poll = queue.poll();
            if (poll != null) {
                System.out.println("虚引用被回收了:" + poll);
            }
        }
    }).start();
    
   Scanner scanner = new Scanner(System.in);
    scanner.hasNext();
}
  • 输出结果
    在这里插入图片描述

5.总结

引用类型被垃圾回收时间用途生存时间
强引用从来不会对象的一般状态JVM停止运行时终止
软引用在内存不足时对象缓存内存不足时终止
弱引用在垃圾回收时对象缓存gc运行后终止
虚引用UnknownUnknownUnknown

6.软引用实例

1.简单的说

软引用和弱引用都可以关联一个队列,但不是必须的
当引用的对象被回收时候,他们自己就会被放到队列中

2.实例

功能:
设置堆内存大小 20M
list中循环添加5个 4M大小的byte(byte用SoftReference包裹着)
这样,当内存不足的时候,会把这些内存回收掉(并且把list中的SoftReference也剔除),而不是抛出异常

package cn.itcast.jvm.t2;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;

/**
 * 演示软引用, 配合引用队列
 */
public class Demo2_4 {
    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) {
        List<SoftReference<byte[]>> list = new ArrayList<>();

        // 引用队列
        ReferenceQueue<byte[]> queue = new ReferenceQueue<>();

        for (int i = 0; i < 5; i++) {
            // 关联了引用队列, 当软引用所关联的 byte[]被回收时,软引用自己会加入到 queue 中去
            SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB], queue);
            System.out.println(ref.get());
            list.add(ref);
            System.out.println(list.size());
        }

        // 从队列中获取无用的 软引用对象,并移除
        //poll()返回的就是SoftReference
        Reference<? extends byte[]> poll = queue.poll();
        while( poll != null) {
            list.remove(poll);
            poll = queue.poll();
        }

        System.out.println("===========================");
        for (SoftReference<byte[]> reference : list) {
            System.out.println(reference.get());
        }

    }
}

7.弱引用实例

1.用法

和软引用的用法都一样
只是弱引用和软引用之间有差别

2.实例

内存不足时,执行GC,然后弱引用就会被回收一次

package cn.itcast.jvm.t2;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * 演示弱引用
 * -Xmx20m -XX:+PrintGCDetails -verbose:gc
 */
public class Demo2_5 {
    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) {
        //  list --> WeakReference --> byte[]
        List<WeakReference<byte[]>> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            WeakReference<byte[]> ref = new WeakReference<>(new byte[_4MB]);
            list.add(ref);
            for (WeakReference<byte[]> w : list) {
                System.out.print(w.get()+" ");
            }
            System.out.println();

        }
        System.out.println("循环结束:" + list.size());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值