【WeakReference】WeakReference 弱引用的认识

1  前言

这节我们聊聊 WeakReference 弱引用的作用,因为我们平时看源码的时候会发现一些对象是继承了这个类的,那么这个类是干什么的?

我的理解哈这个类是专门给 GC 标识用的,当一个类 A 继承了 WeakReference 就表示 A 如果没有别的强引用的话,我 GC 的时候是可以回收掉 A对象的,下边我们会有示例讲解。

2  简介

WeakReference 简称弱引用/软引用

特定:弱引用的对象会在GC时被回收,无论系统内存是否足够。

常用场景:大量对象的创建可能会出现OOM异常,利用弱引用或软引用可以在堆内存不足时回收部分对象,释放空间。

我们简单来看下 WeakReference 的类图,关系比较简单就是继承了引用类。

可以看看 WeakReference 的构造方法就是传入我们的真实对象:

/**
 * Reference 类
 * @param referent 我们的真实对象
 */
Reference(T referent) {
    this(referent, null);
}
/**
 * WeakReference类
 * @param referent 我们的真实对象
 */
public WeakReference(T referent) {
    super(referent);
}

再来看一个 get 方法,就是返回我们的真实对象:

// Reference 类
public T get() {
    return this.referent;
}

3  测试与感知

简单介绍了 WeakReference 我们就来测测它的具体效果,代码示例如下:

public class TestWeakReference {
    // Person类
    static class Person {
        private String name;

        Person(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    // Person的弱引用类
    static class PersonWeakReference extends WeakReference<Person> {
        public PersonWeakReference(Person referent) {
            super(referent);
        }
    }

    public static void main(String[] args) {
        // 创建弱引用
        PersonWeakReference personWeakReference = new PersonWeakReference(new Person("狗子"));
        System.out.println("回收前:" + personWeakReference.get());
        // GC 进行回收,并不会立刻执行,只是建议 jvm 进行 gc
        System.gc();
        System.out.println("回收后:" + personWeakReference.get());
    }
}

IDEA 配置上GC日志,可以看是否有 GC 发生。

3.1  单纯的弱引用

public static void main(String[] args) {
    // 创建弱引用
    PersonWeakReference personWeakReference = new PersonWeakReference(new Person("狗子"));
    System.out.println("回收前:" + personWeakReference.get());
    // GC 进行回收,并不会立刻执行,只是建议 jvm 进行 gc
    System.gc();
    System.out.println("回收后:" + personWeakReference.get());
}

3.2  存在强引用

public static void main(String[] args) {
    // 这里有个强引用
    Person person = new Person("狗子");
    // 创建弱引用
    PersonWeakReference personWeakReference = new PersonWeakReference(person);
    System.out.println("回收前:" + personWeakReference.get());
    // GC 进行回收,并不会立刻执行,只是建议 jvm 进行 gc
    System.gc();
    System.out.println("回收后:" + personWeakReference.get());
}

3.3  OOM的角度感知

配置 -Xmx50m 设置堆的大小,然后我们写一个内存溢出的例子:

public static void main(String[] args) {
    List<byte[]> list = new ArrayList<>();
    for (int i = 0; i < 50; i++) {
        // 1024B = 1K 再乘 1024 = 1M
        byte[] item = new byte[1024 * 1024];
        list.add(item);
    }
}

 那我们用弱引用再来感知下:

static class ByteWeakReference extends WeakReference<byte[]> {
    public ByteWeakReference(byte[] referent) {
        super(referent);
    }
}
public static void main(String[] args) {
    List<ByteWeakReference> list = new ArrayList<>();
    for (int i = 0; i < 50; i++) {
        // 1024B = 1K 再乘 1024 = 1M
        ByteWeakReference byteWeakReference = new ByteWeakReference(new byte[1024 * 1024]);
        list.add(byteWeakReference);
    }
}

4  小结

这节我们主要认识了一下 WeakReference 弱引用,它主要是用来影响一个 GC的效果,也从几个测试点大概感受了下,有理解不对的地方欢迎指正哈。

posted @ 2023-03-16 08:18  酷酷-  阅读(141)  评论(0编辑  收藏  举报