# Java 的引用

java 的引用分为强,软,弱,虚

# 什么是引用

定义变量指向堆内存中的一个地址, 我们就说这个变量和内存地址之间建立了一条引用.

# 强引用

不会被 GC 回收.

普通的引用, Object o = new Object() 创建一个对象, 这样就是强引用.

# 软引用

当内存不够用的时候, 软引用才会被回收.

public class T02_SoftReference {
    public static void main(String[] args) {
        SoftReference<byte[]> m = new SoftReference<>(new byte[1024*1024*10]);
        //m = null;
        System.out.println(m.get());
        System.gc();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(m.get());

        //再分配一个数组,heap将装不下,这时候系统会垃圾回收,先回收一次,如果不够,会把软引用干掉
        byte[] b = new byte[1024*1024*15];
        System.out.println(m.get());
    }
    //软引用非常适合缓存使用
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 弱引用

只要遭遇到 GC 就会被回收.

一般用在容器里

public class T03_WeakReference {
    public static void main(String[] args) {
        WeakReference<M> m = new WeakReference<>(new M());

        System.out.println(m.get());
        System.gc();
        System.out.println(m.get());


        ThreadLocal<M> tl = new ThreadLocal<>();
        tl.set(new M());
        tl.remove();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

注意: ThreadLocal 使用完之后, 手动 remove

弱引用在 ThreadLocal 中的使用.

# 虚引用

主要用于堆外内存, 基本不会用到(给写虚拟机的人用的)

虚引用的值永远不会被 get

public class T04_PhantomReference {
    private static final List<Object> LIST = new LinkedList<>();
    private static final ReferenceQueue<M> QUEUE = new ReferenceQueue<>();



    public static void main(String[] args) {


        PhantomReference<M> phantomReference = new PhantomReference<>(new M(), QUEUE);


        new Thread(() -> {
            while (true) {
                LIST.add(new byte[1024 * 1024]);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
                System.out.println(phantomReference.get());
            }
        }).start();

        new Thread(() -> {
            while (true) {
                Reference<? extends M> poll = QUEUE.poll();
                if (poll != null) {
                    System.out.println("--- 虚引用对象被jvm回收了 ---- " + poll);
                }
            }
        }).start();

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

上次更新时间: 2020/11/3 下午9:59:57