聊聊Java的引用

在JDK1.2之后,Java对引用的概念进行了扩充,将引用分为强引用(Storngly Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4种,其中这四种引用强度为强引用 > 软引用 > 弱引用 > 虚引用

# 强引用(Storngly Reference)

强引用是最传统的“引用”的定义,是指在程序代码之中普遍存在的引用赋值,即类似Object obj = new Object()这种引用关系。无论任何情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象。如果强引用对象不再需要时,需要将强引用关系弱化从而使垃圾回收器能够将其回收:

obj = null
1

在一个方法的内部有一个强引用,这个引用保存在Java栈中,而真正的引用内容(Object)保存在Java堆中。

public void m() {
    Object obj = new Object()
}
1
2
3

当这个方法运行完成后,就会退出方法栈,则引用对象的引用数为0,这个对象会被回收。但是如果这个obj是全局变量时,就需要在不用这个对象时赋值为null,因为强引用不会被垃圾回收.

在ArrayList类中定义了一个elementData数组,在调用clear方法清空数组时,每个数组元素被赋值为null。不同于elementData=null,强引用仍然存在,避免在后续调用add()等方法添加元素时进行内存的重新分配。使用如clear()方法内存数组中存放的引用类型进行内存释放特别适用,这样就可以及时释放内存。

/**
* Removes all of the elements from this list.  The list will
* be empty after this call returns.
*/
public void clear() {
    modCount++;
    // clear to let GC do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;
    size = 0;
}
1
2
3
4
5
6
7
8
9
10
11

# 软引用(Soft Reference)

软引用是用来描述一些还有用,但非必须的对象。只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。在JDK 1.2版之后提供了SoftReference类来实现软引用。

String str = new String("str");
SoftReference<String> softReference = new SoftReference<>(str);
1
2

软引用可以和一个引用队列ReferenceQueue联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。一般用于缓存,利用OOM时回收的特性设置缓存的场景。Mybatis中的本地缓存SoftCache就是使用 SoftReference模式,本地内存不足时会回收cache中的对象。

# 弱引用(Weak Reference)

弱引用也是用来描述那些非必须对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK 1.2版之后提供了WeakReference类来实现弱引用。一般用于缓存,利用每次GC时回收的特性设置缓存的场景,比如ThreadLocal。

/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object).  Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table.  Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 虚引用(Phantom Reference)

虚引用也称为“幽灵引用”或者“幻影引用”,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。在JDK 1.2版之后提供了PhantomReference类来实现虚引用。

上次更新: 2020/08/25, 15:08:00
最近更新
01
RabbitMQ简介
10-27
02
聊聊Java多态
10-21
03
JVM垃圾回收器
10-16
更多文章>