【JAVA Reference】Java的强引用、软引用、弱引用和虚引用(一)

我的原则:先会用再说,内部慢慢来。
学以致用,根据场景学源码


一、概念与区别

  1. Java中4种引用的强度由高到低依次为:强引用 -> 软引用 -> 弱引用 -> 虚引用
  2. 用途与区别:
引用类型 被垃圾回收时机 用途 生存时间
强引用 从来不会 对象的一般状态 JVM停止运行时终止
软引用 当内存不足前 对象缓存 内存不足时终止
弱引用 GC一看到立刻回收 对象缓存 垃圾回收后终止
虚引用 随时随刻 跟踪对象的垃圾回收 垃圾回收后终止

二、架构

在这里插入图片描述
=== 点击查看top目录 ===

三、代码demo

3.1 强引用 Strong Reference

  • 生命周期:JVM 宁愿抛出OutOfMemoryError错误。

代码demo:

    Object strongReference = new Object();
public void hello() {
        Object strongReference = new Object();
        // ...
    }

GC回收时机:

  1. strongReference = null,那么无引用指向该 new Object()。
  2. 方法结束,java方法栈中局部变量被回收。

否则:JVM 宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会GC该对象来解决内存不足的问题。

=== 点击查看top目录 ===

3.2 软引用 (SoftReference)

  • 生命周期:JVM 抛出OutOfMemoryError错误之前,回收这个软引用指向的对象堆内占用的空间。

目的:尽可能保留该对象,但是万不得已没内存的时候,可以进行回收

GC回收时机:

  1. strongReference = null,那么无引用指向该 new Object()。
  2. 方法结束,java方法栈中局部变量被回收。
  3. 堆内存不足,准备抛出OutOfMemoryError错误之前,处理一波软引用。

注意:软引用就算你调用 System.gc() 在内存充足的情况下,也不会回收这个对象的。

场景:浏览器的后退按钮。(缓存数据能保证加载快,但是内存不足的情况下,被回收了,重新去服务器加载也是可以接受的)

代码demo:

// 获取浏览器对象进行浏览
    Browser browser = new Browser();
    // 从后台程序加载浏览页面
    BrowserPage page = browser.getPage();
    // 将浏览完毕的页面置为软引用
    SoftReference softReference = new SoftReference(page);

    // 回退或者再次浏览此页面时
    if(softReference.get() != null) {
        // 内存充足,还没有被回收器回收,直接获取缓存
        page = softReference.get();
    } else {
        // 内存不足,软引用的对象已经回收
        page = browser.getPage();
        // 重新构建软引用
        softReference = new SoftReference(page);
    }

=== 点击查看top目录 ===

3.3 弱引用 (WeakReference)

  • 生命周期:GC一看到,立马消灭(首次看到标记,下次gc回收)
  • 使用场景:
  1. 一个对象是偶尔(很少)的使用
  2. 一定程度上可以避免内存泄漏(详看 ThreadLocal类)

【线程】ThreadLocal 剖析 (十四)

  • ThreadLocal.ThreadLocalMap.Entry
public class ThreadLocal<T> {
	static class ThreadLocalMap {
		static class Entry extends WeakReference<ThreadLocal<?>> {
		    Object value;
		    Entry(ThreadLocal<?> k, Object v) {
		        super(k);
		        value = v;
		    }
		}
	}
}
  • Thread
public java.lang.class Thread implements Runnable {
	...     
    ThreadLocal.ThreadLocalMap threadLocals = null;
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
    ...
}

4. 虚引用(PhantomReference)

  • 生命周期:任何时候都可能被GC回收 (如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收)

代码demo:

public class _03_00_TestPhamtonReference {
    public static void main(String[] args) {
        ReferenceQueue<String> referenceQueue = new ReferenceQueue<>();
        PhantomReference<String> phantomReference = new PhantomReference<>("hello",referenceQueue);
        System.out.println(phantomReference.get());
    }
}

输出:

null

结论:
刚一出来就被消灭

=== 点击查看top目录 ===


四、番外篇

下一章节:【JAVA Reference】ReferenceQueue 与 Reference 源码剖析(二)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章