Java 学习笔记

所有文章
📖 最新文章 transmittable-thread-local 库 JOOR 反射库 Lombok 库:为你减少样板代码 Slf4j 日志组件的使用 加速maven、gradle依赖下载
📖 Java 基础 安装 第一个程序 使用 UTF-8 编写代码 空值 null 正则表达式 线程 日期/时间 匿名类 枚举 ThreadLocal 线程本地变量 动态代理 jar 命令

Java 引用级别:强引用、软引用、弱引用、幽灵引用


本文的示例中需要触发垃圾回收,用了Java 如何触发垃圾回收 给出的方法。

强引用

我们通常写的将对象赋值给变量,都是强引用。

public class Main {

    static class Person {
        String name;

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

        @Override
        public String toString() {
            return "name=" + name;
        }
    }

    public static void main(String[] args) {

        Person ltt = new Person("ltt");  // ltt 变量对这个 Person 对象进行了强引用
        System.out.println(ltt);

        System.gc();
        System.runFinalization();

        System.out.println(ltt);  // gc 后,被强引用的对象还在
    }

}

输出:

name=ltt
name=ltt

软引用 SoftReference

当一个对象没有强引用,但有弱引用时,如果JVM内存不足,会将该对象回收。

import java.lang.ref.SoftReference;

public class Main {

    static class Person {
        String name;

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

        @Override
        public String toString() {
            return "name=" + name;
        }
    }

    public static void main(String[] args) {

        Person ltt = new Person("ltt");
        System.out.println(ltt);  // name=ltt

        SoftReference<Person> lttRef = new SoftReference<>(ltt);  // lttRef 对 Person 对象进行弱引用
        ltt = null;  // 去掉对  Person 对象的强引用

        System.out.println(lttRef.get());  // name=ltt

        System.gc();
        System.runFinalization();

        // 因为内存尚充足,所以 Person 对象还在
        System.out.println(lttRef.get());  // name=ltt
    }

}

输出:

name=ltt
name=ltt
name=ltt

弱引用 WeakReference

当一个对象只有弱引用时,gc时会把该对象回收。

import java.lang.ref.WeakReference;

public class Main {

    static class Person {
        String name;

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

        @Override
        public String toString() {
            return "name=" + name;
        }
    }

    public static void main(String[] args) {

        Person ltt = new Person("ltt");
        System.out.println(ltt);  // name=ltt

        WeakReference<Person> lttRef = new WeakReference<>(ltt);
        ltt = null;

        System.out.println(lttRef.get());  // name=ltt

        System.gc();
        System.runFinalization();

        // 被回收了,所以下面输出 null
        System.out.println(lttRef.get());  // null
    }

}

输出:

name=ltt
name=ltt
null

幽灵引用

如果一个对象只有幽灵引用,相当于没有任何引用,我们再也找不到它。在gc时,该对象会被回收。

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class Main {

    static class Person {
        String name;

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

        @Override
        public String toString() {
            return "name=" + name;
        }
    }

    public static void main(String[] args) {

        Person ltt = new Person("ltt");
        System.out.println(ltt);  // name=ltt

        ReferenceQueue queue = new ReferenceQueue();
        PhantomReference<Person> lttRef = new PhantomReference<>(ltt, queue);
        ltt = null;

        // 没有 gc 也找不到对象了
        System.out.println(lttRef.get());  // null
    }

}

运行输出:

name=ltt
null
null

关于 ReferenceQueue,可以参考 Java ReferenceQueue


( 本文完 )

文章目录