java中的4种引用和GC Roots
阅读原文时间:2023年07月08日阅读:1

https://juejin.im/post/5d06de9d51882559ee6f4212?utm_source=gold_browser_extension

1.首先,四种引用如下:

  • FinalReference 强引用
  • SoftReference 软引用
  • WeakReference 弱引用
  • PhantomReference 虚引用

2.四种引用的特点:

强引用:被new出来的对象都是的引用都是强引用

eg:Student s = new Student();

回收时机:不会被回收,会发生内存溢出。

软引用:软引用关联的对象,在内存不够的情况下,会把这些软引用关联的对象列入垃圾回收范围中,然后进行回收,也就是说软引用并非是完全安全的,在内存不够的情况下是会被垃圾回收器回收掉的。

public static void main(String\[\] args) {  
    SoftReference\[\] references = new SoftReference\[5\];  
    ReferenceQueue<ReferenceTestObject> referenceTestObjectReferenceQueue = new ReferenceQueue<>();  
    for(int i =0 ;i<5;i++){  
        references\[i\] = new SoftReference(new ReferenceTestObject("ahahh-"+i),referenceTestObjectReferenceQueue);  
    }

    for(int i =0 ;i<5;i++){  
        Object o = references\[i\].get();  
        if(o == null){  
            System.out.println("null");  
        }else{  
            System.out.println(((ReferenceTestObject)o).name);  
        }  
    }  
}

使用场景:使用软引用来保存从数据库中取出的数据,具体是做了一个中间层的封装,该中间层的作用就是在get出数据的时候会去判断数据是否为null,如果是为null再次从数据库读取,读取后再放入软引用的集合中,这样的做法是可以避免内存溢出

弱引用:只要发生GC都会被回收掉

eg:ThreadLocalMap的key

static class ThreadLocalMap {

    /\*\*  
     \* 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;  
        }  
    }  
......}

虚引用
有和没有一个样:无法通过虚引用来获取对象的实例,但是还是有作用的。、
作用就是能在这个对象被收集器回收时收到一个系统通知,实现追踪垃圾收集器的回收动作,比如在对象被回收的时候,会调用该对象的finalize方法。

ReferenceQueue 引用队列

在创建Reference时,手动将Queue注册到Reference中,而当该Reference所引用的对象被垃圾收集器回收时,JVM会将该Reference放到该队列中,而我们便可以对该队列做些其他业务,相当于一种通知机制。

可达性分析:

JVM怎么知道引用在不在,这就涉及到了JVM的可达性分析算法了 JVM的可达性分析算法的简单思路就是通过一系列GC Roots作为出发点,向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链,即表明从GC Roots到这个对象不可达时,证明此对象不可用,可被回收。如下图所示

对象4、5、6都是可被回收的。 那么问题来了,哪些对象可以作为GC Roots呢? 这里给出几个,如下

  • 虚拟机栈中引用的对象

  • 方法区中类静态属性引用的对象

  • 方法区中常量引用的对象

  • 本地方法栈JNI引用的对象