Java四种Reference类型测试和PhtantomReference的应用示例

环境

    /**
     * -Xmx64M 最大堆大小
     * -Xms64M  初始化堆大小
     * -XX:+PrintGCDetails 在控制台输出GC详细信息
     * -Xmx64M -Xms64M -XX:+PrintGCDetails
     */
     jdk\jdk11.0.9_11\bin\java.exe -Xmx64M -Xms64M -XX:+PrintGCDetails

StrongReference

是我们平时使用最多的一种对象引用,当一个对象被关键字new实例化出来的时候,JVM会在堆内存开辟一片内存区域,用于存放与该实例对应的数据结构。
JVM垃圾回收器线程会在达到GC条件时尝试回收堆栈内存中的数据,强引用的的点是只要应用到ROOT根的路径可达,无论怎样的GC都不会将其释放,而是宁可出现JVM内存溢出。
如Object object =new Object();
String str =“hello world”;

private void testStrongReference() {

 List<Reference>  list = new ArrayList<>();
        for (int i=0; i< 10; i++) {
            Reference reference = new Reference();
            list.add(reference);
        }
        System.out.println(list.size());
        /**
         * jdk\jdk11.0.9_11\bin\java.exe -Xmx64M -Xms64M -XX:+PrintGCDetails
         * [0.004s][warning][gc] -XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead.
         * [0.015s][info   ][gc,heap] Heap region size: 1M
         * [0.018s][info   ][gc     ] Using G1
         * [0.018s][info   ][gc,heap,coops] Heap address: 0x00000000fc000000, size: 64 MB, Compressed Oops mode: 32-bit
         * [0.147s][info   ][gc,start     ] GC(0) Pause Young (Concurrent Start) (G1 Humongous Allocation)
         * [0.147s][info   ][gc,task      ] GC(0) Using 2 workers of 10 for evacuation
         * [0.149s][info   ][gc,phases    ] GC(0)   Pre Evacuate Collection Set: 0.0ms
         * [0.149s][info   ][gc,phases    ] GC(0)   Evacuate Collection Set: 1.5ms
         * [0.149s][info   ][gc,phases    ] GC(0)   Post Evacuate Collection Set: 0.1ms
         * [0.149s][info   ][gc,phases    ] GC(0)   Other: 0.3ms
         * [0.149s][info   ][gc,heap      ] GC(0) Eden regions: 4->0(29)
         * [0.149s][info   ][gc,heap      ] GC(0) Survivor regions: 0->1(3)
         * [0.149s][info   ][gc,heap      ] GC(0) Old regions: 0->0
         * [0.149s][info   ][gc,heap      ] GC(0) Humongous regions: 22->22
         * [0.149s][info   ][gc,metaspace ] GC(0) Metaspace: 6403K->6403K(1056768K)
         * [0.149s][info   ][gc           ] GC(0) Pause Young (Concurrent Start) (G1 Humongous Allocation) 25M->22M(64M) 2.060ms
         * [0.149s][info   ][gc,cpu       ] GC(0) User=0.00s Sys=0.00s Real=0.00s
         * [0.149s][info   ][gc           ] GC(1) Concurrent Cycle
         * [0.149s][info   ][gc,marking   ] GC(1) Concurrent Clear Claimed Marks
         * [0.149s][info   ][gc,marking   ] GC(1) Concurrent Clear Claimed Marks 0.005ms
         * [0.149s][info   ][gc,marking   ] GC(1) Concurrent Scan Root Regions
         * [0.150s][info   ][gc,marking   ] GC(1) Concurrent Scan Root Regions 0.464ms
         * [0.150s][info   ][gc,marking   ] GC(1) Concurrent Mark (0.150s)
         * [0.150s][info   ][gc,marking   ] GC(1) Concurrent Mark From Roots
         * [0.150s][info   ][gc,task      ] GC(1) Using 3 workers of 3 for marking
         * [0.150s][info   ][gc,marking   ] GC(1) Concurrent Mark From Roots 0.301ms
         * [0.150s][info   ][gc,marking   ] GC(1) Concurrent Preclean
         * [0.150s][info   ][gc,marking   ] GC(1) Concurrent Preclean 0.123ms
         * [0.150s][info   ][gc,marking   ] GC(1) Concurrent Mark (0.150s, 0.150s) 0.453ms
         * [0.153s][info   ][gc,start     ] GC(1) Pause Remark
         * [0.154s][info   ][gc,stringtable] GC(1) Cleaned string and symbol table, strings: 2912 processed, 0 removed, symbols: 26607 processed, 0 removed
         * [0.154s][info   ][gc            ] GC(1) Pause Remark 33M->33M(64M) 0.582ms
         * [0.154s][info   ][gc,cpu        ] GC(1) User=0.00s Sys=0.00s Real=0.00s
         * [0.154s][info   ][gc,marking    ] GC(1) Concurrent Rebuild Remembered Sets
         * [0.154s][info   ][gc,marking    ] GC(1) Concurrent Rebuild Remembered Sets 0.073ms
         * [0.158s][info   ][gc,start      ] GC(1) Pause Cleanup
         * [0.158s][info   ][gc            ] GC(1) Pause Cleanup 45M->45M(64M) 0.081ms
         * [0.158s][info   ][gc,cpu        ] GC(1) User=0.00s Sys=0.00s Real=0.00s
         * [0.158s][info   ][gc,marking    ] GC(1) Concurrent Cleanup for Next Mark
         * [0.158s][info   ][gc,marking    ] GC(1) Concurrent Cleanup for Next Mark 0.075ms
         * [0.158s][info   ][gc            ] GC(1) Concurrent Cycle 8.769ms
         * [0.162s][info   ][gc,start      ] GC(2) Pause Young (Concurrent Start) (G1 Humongous Allocation)
         * [0.162s][info   ][gc,task       ] GC(2) Using 2 workers of 10 for evacuation
         * [0.163s][info   ][gc,phases     ] GC(2)   Pre Evacuate Collection Set: 0.0ms
         * [0.163s][info   ][gc,phases     ] GC(2)   Evacuate Collection Set: 1.1ms
         * [0.163s][info   ][gc,phases     ] GC(2)   Post Evacuate Collection Set: 0.1ms
         * [0.163s][info   ][gc,phases     ] GC(2)   Other: 0.1ms
         * [0.163s][info   ][gc,heap       ] GC(2) Eden regions: 1->0(2)
         * [0.163s][info   ][gc,heap       ] GC(2) Survivor regions: 1->1(4)
         * [0.163s][info   ][gc,heap       ] GC(2) Old regions: 0->0
         * [0.163s][info   ][gc,heap       ] GC(2) Humongous regions: 55->55
         * [0.163s][info   ][gc,metaspace  ] GC(2) Metaspace: 6403K->6403K(1056768K)
         * [0.163s][info   ][gc            ] GC(2) Pause Young (Concurrent Start) (G1 Humongous Allocation) 56M->56M(64M) 1.339ms
         * [0.163s][info   ][gc,cpu        ] GC(2) User=0.00s Sys=0.00s Real=0.00s
         * [0.164s][info   ][gc            ] GC(3) Concurrent Cycle
         * [0.164s][info   ][gc,marking    ] GC(3) Concurrent Clear Claimed Marks
         * [0.164s][info   ][gc,marking    ] GC(3) Concurrent Clear Claimed Marks 0.005ms
         * [0.164s][info   ][gc,marking    ] GC(3) Concurrent Scan Root Regions
         * [0.164s][info   ][gc,marking    ] GC(3) Concurrent Scan Root Regions 0.509ms
         * [0.164s][info   ][gc,marking    ] GC(3) Concurrent Mark (0.164s)
         * [0.164s][info   ][gc,marking    ] GC(3) Concurrent Mark From Roots
         * [0.164s][info   ][gc,start      ] GC(4) Pause Young (Normal) (G1 Humongous Allocation)
         * [0.164s][info   ][gc,task       ] GC(3) Using 3 workers of 3 for marking
         * [0.164s][info   ][gc,task       ] GC(4) Using 2 workers of 10 for evacuation
         * [0.165s][info   ][gc,phases     ] GC(4)   Pre Evacuate Collection Set: 0.4ms
         * [0.165s][info   ][gc,phases     ] GC(4)   Evacuate Collection Set: 1.1ms
         * [0.165s][info   ][gc,phases     ] GC(4)   Post Evacuate Collection Set: 0.1ms
         * [0.165s][info   ][gc,phases     ] GC(4)   Other: 0.0ms
         * [0.165s][info   ][gc,heap       ] GC(4) Eden regions: 0->0(2)
         * [0.165s][info   ][gc,heap       ] GC(4) Survivor regions: 1->1(1)
         * [0.165s][info   ][gc,heap       ] GC(4) Old regions: 0->1
         * [0.165s][info   ][gc,heap       ] GC(4) Humongous regions: 55->55
         * [0.165s][info   ][gc,metaspace  ] GC(4) Metaspace: 6403K->6403K(1056768K)
         * [0.165s][info   ][gc            ] GC(4) Pause Young (Normal) (G1 Humongous Allocation) 56M->56M(64M) 1.248ms
         * [0.165s][info   ][gc,cpu        ] GC(4) User=0.00s Sys=0.00s Real=0.00s
         * [0.165s][info   ][gc,task       ] GC(5) Using 2 workers of 10 for full compaction
         * [0.165s][info   ][gc,start      ] GC(5) Pause Full (G1 Humongous Allocation)
         * [0.165s][info   ][gc,phases,start] GC(5) Phase 1: Mark live objects
         * [0.166s][info   ][gc,stringtable ] GC(5) Cleaned string and symbol table, strings: 2912 processed, 3 removed, symbols: 26607 processed, 0 removed
         * [0.166s][info   ][gc,phases      ] GC(5) Phase 1: Mark live objects 0.998ms
         * [0.166s][info   ][gc,phases,start] GC(5) Phase 2: Prepare for compaction
         * [0.167s][info   ][gc,phases      ] GC(5) Phase 2: Prepare for compaction 0.270ms
         * [0.167s][info   ][gc,phases,start] GC(5) Phase 3: Adjust pointers
         * [0.167s][info   ][gc,phases      ] GC(5) Phase 3: Adjust pointers 0.571ms
         * [0.167s][info   ][gc,phases,start] GC(5) Phase 4: Compact heap
         * [0.168s][info   ][gc,phases      ] GC(5) Phase 4: Compact heap 0.270ms
         * [0.168s][info   ][gc,heap        ] GC(5) Eden regions: 0->0(3)
         * [0.168s][info   ][gc,heap        ] GC(5) Survivor regions: 1->0(1)
         * [0.168s][info   ][gc,heap        ] GC(5) Old regions: 1->2
         * [0.168s][info   ][gc,heap        ] GC(5) Humongous regions: 55->55
         * [0.168s][info   ][gc,metaspace   ] GC(5) Metaspace: 6403K->6403K(1056768K)
         * [0.168s][info   ][gc             ] GC(5) Pause Full (G1 Humongous Allocation) 56M->55M(64M) 2.429ms
         * [0.168s][info   ][gc,cpu         ] GC(5) User=0.00s Sys=0.00s Real=0.00s
         * [0.168s][info   ][gc,task        ] GC(6) Using 2 workers of 10 for full compaction
         * [0.168s][info   ][gc,start       ] GC(6) Pause Full (G1 Humongous Allocation)
         * [0.168s][info   ][gc,phases,start] GC(6) Phase 1: Mark live objects
         * [0.169s][info   ][gc,stringtable ] GC(6) Cleaned string and symbol table, strings: 2909 processed, 2 removed, symbols: 26607 processed, 0 removed
         * [0.169s][info   ][gc,phases      ] GC(6) Phase 1: Mark live objects 0.959ms
         * [0.169s][info   ][gc,phases,start] GC(6) Phase 2: Prepare for compaction
         * [0.169s][info   ][gc,phases      ] GC(6) Phase 2: Prepare for compaction 0.341ms
         * [0.169s][info   ][gc,phases,start] GC(6) Phase 3: Adjust pointers
         * [0.170s][info   ][gc,phases      ] GC(6) Phase 3: Adjust pointers 0.548ms
         * [0.170s][info   ][gc,phases,start] GC(6) Phase 4: Compact heap
         * [0.170s][info   ][gc,phases      ] GC(6) Phase 4: Compact heap 0.247ms
         * [0.170s][info   ][gc,heap        ] GC(6) Eden regions: 0->0(3)
         * [0.170s][info   ][gc,heap        ] GC(6) Survivor regions: 0->0(1)
         * [0.170s][info   ][gc,heap        ] GC(6) Old regions: 2->2
         * [0.170s][info   ][gc,heap        ] GC(6) Humongous regions: 55->55
         * [0.170s][info   ][gc,metaspace   ] GC(6) Metaspace: 6403K->6403K(1056768K)
         * [0.170s][info   ][gc             ] GC(6) Pause Full (G1 Humongous Allocation) 55M->55M(64M) 2.340ms
         * [0.170s][info   ][gc,cpu         ] GC(6) User=0.00s Sys=0.00s Real=0.00s
         * [0.170s][info   ][gc,marking     ] GC(3) Concurrent Mark From Roots 6.423ms
         * [0.170s][info   ][gc,marking     ] GC(3) Concurrent Mark Abort
         * [0.170s][info   ][gc             ] GC(3) Concurrent Cycle 6.989ms
         * Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
         * 	at com.james.example.thread.jcp_multithread_architecture.chapter25.ReferenceTest$Reference.<init>(ReferenceTest.java:174)
         * 	at com.james.example.thread.jcp_multithread_architecture.chapter25.ReferenceTest.main(ReferenceTest.java:27)
         * [0.172s][info   ][gc,heap,exit   ] Heap
         * [0.172s][info   ][gc,heap,exit   ]  garbage-first heap   total 65536K, used 57292K [0x00000000fc000000, 0x0000000100000000)
         * [0.172s][info   ][gc,heap,exit   ]   region size 1024K, 1 young (1024K), 0 survivors (0K)
         * [0.172s][info   ][gc,heap,exit   ]  Metaspace       used 6419K, capacity 6479K, committed 6528K, reserved 1056768K
         * [0.172s][info   ][gc,heap,exit   ]   class space    used 566K, capacity 602K, committed 640K, reserved 1048576K
         */
    }
}

SoftReference

如果一个对象具有软引用,内存空间足够,垃圾回收器就不会回收它;
如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存,比如网页缓存、图片缓存等。使用软引用能防止内存泄露,增强程序的健壮性。
特点是它的一个实例保存对一个Java对象的软引用, 该软引用的存在不妨碍垃圾收集线程对该Java对象的回收。也就是说,一旦SoftReference保存了对一个Java对象的软引用后,在垃圾线程对 这个Java对象回收前,SoftReference类所提供的get()方法返回Java对象的强引用。
注意: 一旦垃圾线程回收该Java对象之 后,get()方法将返回null。

   private static void testSoftReference() {
        /**
         * 只有当内存不够时,执行GC时才会回收
         */
        Reference ref = new Reference();
        SoftReference<Reference> softReference = new SoftReference<>(ref);
        ref = null;
        System.gc();
        /**
         * jdk\jdk11.0.9_11\bin\java.exe -Xmx64M -Xms64M -XX:+PrintGCDetails
         * [0.004s][warning][gc] -XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead.
         * [0.014s][info   ][gc,heap] Heap region size: 1M
         * [0.016s][info   ][gc     ] Using G1
         * [0.016s][info   ][gc,heap,coops] Heap address: 0x00000000fc000000, size: 64 MB, Compressed Oops mode: 32-bit
         * [0.132s][info   ][gc,task      ] GC(0) Using 2 workers of 10 for full compaction
         * [0.132s][info   ][gc,start     ] GC(0) Pause Full (System.gc())
         * [0.132s][info   ][gc,phases,start] GC(0) Phase 1: Mark live objects
         * [0.133s][info   ][gc,stringtable ] GC(0) Cleaned string and symbol table, strings: 2911 processed, 3 removed, symbols: 26557 processed, 0 removed
         * [0.133s][info   ][gc,phases      ] GC(0) Phase 1: Mark live objects 1.543ms
         * [0.133s][info   ][gc,phases,start] GC(0) Phase 2: Prepare for compaction
         * [0.134s][info   ][gc,phases      ] GC(0) Phase 2: Prepare for compaction 0.275ms
         * [0.134s][info   ][gc,phases,start] GC(0) Phase 3: Adjust pointers
         * [0.134s][info   ][gc,phases      ] GC(0) Phase 3: Adjust pointers 0.512ms
         * [0.134s][info   ][gc,phases,start] GC(0) Phase 4: Compact heap
         * [0.135s][info   ][gc,phases      ] GC(0) Phase 4: Compact heap 0.534ms
         * [0.135s][info   ][gc,heap        ] GC(0) Eden regions: 4->0(23)
         * [0.135s][info   ][gc,heap        ] GC(0) Survivor regions: 0->0(0)
         * [0.135s][info   ][gc,heap        ] GC(0) Old regions: 0->2
         * [0.135s][info   ][gc,heap        ] GC(0) Humongous regions: 11->11
         * [0.135s][info   ][gc,metaspace   ] GC(0) Metaspace: 6357K->6357K(1056768K)
         * [0.135s][info   ][gc             ] GC(0) Pause Full (System.gc()) 14M->11M(64M) 3.199ms
         * [0.135s][info   ][gc,cpu         ] GC(0) User=0.02s Sys=0.00s Real=0.00s
         * [0.136s][info   ][gc,heap,exit   ] Heap
         * [0.136s][info   ][gc,heap,exit   ]  garbage-first heap   total 65536K, used 12225K [0x00000000fc000000, 0x0000000100000000)
         * [0.136s][info   ][gc,heap,exit   ]   region size 1024K, 1 young (1024K), 0 survivors (0K)
         * [0.136s][info   ][gc,heap,exit   ]  Metaspace       used 6405K, capacity 6479K, committed 6528K, reserved 1056768K
         * [0.136s][info   ][gc,heap,exit   ]   class space    used 564K, capacity 602K, committed 640K, reserved 1048576K
         */
    }

WeakReferenc

弱引用也是用来描述非必需对象的,当JVM进行任何类型的垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象

/**
     * 无论YoungGc 还是Full GC  无论内存空间是否有空闲,只要执行GC 即被回收
     */
    private static void testWeakReference() {
        Reference ref = new Reference();

        WeakReference<Reference> weakReference = new WeakReference<>(ref);
        ref = null;
        System.gc();
        /**
         * jdk\jdk11.0.9_11\bin\java.exe -Xmx64M -Xms64M -XX:+PrintGCDetails
         * [0.005s][warning][gc] -XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead.
         * [0.015s][info   ][gc,heap] Heap region size: 1M
         * [0.017s][info   ][gc     ] Using G1
         * [0.017s][info   ][gc,heap,coops] Heap address: 0x00000000fc000000, size: 64 MB, Compressed Oops mode: 32-bit
         * [0.137s][info   ][gc,task      ] GC(0) Using 2 workers of 10 for full compaction
         * [0.137s][info   ][gc,start     ] GC(0) Pause Full (System.gc())
         * [0.137s][info   ][gc,phases,start] GC(0) Phase 1: Mark live objects
         * [0.138s][info   ][gc,stringtable ] GC(0) Cleaned string and symbol table, strings: 2911 processed, 3 removed, symbols: 26557 processed, 0 removed
         * [0.138s][info   ][gc,phases      ] GC(0) Phase 1: Mark live objects 1.597ms
         * [0.138s][info   ][gc,phases,start] GC(0) Phase 2: Prepare for compaction
         * [0.139s][info   ][gc,phases      ] GC(0) Phase 2: Prepare for compaction 0.390ms
         * [0.139s][info   ][gc,phases,start] GC(0) Phase 3: Adjust pointers
         * [0.139s][info   ][gc,phases      ] GC(0) Phase 3: Adjust pointers 0.647ms
         * [0.139s][info   ][gc,phases,start] GC(0) Phase 4: Compact heap
         * [0.140s][info   ][gc,phases      ] GC(0) Phase 4: Compact heap 0.561ms
         * [0.140s][info   ][gc,heap        ] GC(0) Eden regions: 4->0(23)
         * [0.140s][info   ][gc,heap        ] GC(0) Survivor regions: 0->0(0)
         * [0.140s][info   ][gc,heap        ] GC(0) Old regions: 0->2
         * [0.140s][info   ][gc,heap        ] GC(0) Humongous regions: 11->11
         * [0.140s][info   ][gc,metaspace   ] GC(0) Metaspace: 6356K->6356K(1056768K)
         * [0.140s][info   ][gc             ] GC(0) Pause Full (System.gc()) 14M->11M(64M) 3.602ms
         * [0.140s][info   ][gc,cpu         ] GC(0) User=0.00s Sys=0.00s Real=0.00s
         * the reference will be GC
         * [0.141s][info   ][gc,heap,exit   ] Heap
         * [0.141s][info   ][gc,heap,exit   ]  garbage-first heap   total 65536K, used 13249K [0x00000000fc000000, 0x0000000100000000)
         * [0.141s][info   ][gc,heap,exit   ]   region size 1024K, 2 young (2048K), 0 survivors (0K)
         * [0.141s][info   ][gc,heap,exit   ]  Metaspace       used 6407K, capacity 6479K, committed 6528K, reserved 1056768K
         * [0.141s][info   ][gc,heap,exit   ]   class space    used 564K, capacity 602K, committed 640K, reserved 1048576K
         */
    }

PhantomReference

虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。在java中用java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。需要注意的是:虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

与SoftReference和WeakReference相比较 Phantom Reference不同之处:

  1. Phantom Reference 必须与ReferenceQueue配合使用
  2. Phantom Reference 的get方法返回的始终是null
  3. 当垃圾回收器决定回收Phantom Reference对象的时候会将其插入关联的ReferenceQueue中
  4. 使用Phantom Reference 进行清理动作要比Object的finalize方法更灵活。
 private static void testPhantomReference() {
        ReferenceQueue<String> queue = new ReferenceQueue<String>();
        PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);
        System.out.println(pr.get());

        /**
         * jdk\jdk11.0.9_11\bin\java.exe -Xmx64M -Xms64M -XX:+PrintGCDetails
         * [0.004s][warning][gc] -XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead.
         * [0.015s][info   ][gc,heap] Heap region size: 1M
         * [0.018s][info   ][gc     ] Using G1
         * [0.018s][info   ][gc,heap,coops] Heap address: 0x00000000fc000000, size: 64 MB, Compressed Oops mode: 32-bit
         * null
         * [0.143s][info   ][gc,heap,exit ] Heap
         * [0.143s][info   ][gc,heap,exit ]  garbage-first heap   total 65536K, used 3072K [0x00000000fc000000, 0x0000000100000000)
         * [0.143s][info   ][gc,heap,exit ]   region size 1024K, 4 young (4096K), 0 survivors (0K)
         * [0.143s][info   ][gc,heap,exit ]  Metaspace       used 6171K, capacity 6255K, committed 6528K, reserved 1056768K
         * [0.143s][info   ][gc,heap,exit ]   class space    used 535K, capacity 570K, committed 640K, reserved 1048576K
         */
    }

PhantomReference应用-SocketCleaningTracker



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

/***
 * SocketCleaningTracker 启动Cleaner线程(其被设置为守护线程,清理动作一般是系统的清理工作,
 * 用于防止JVM无法正常关闭,如同JVM的GC线程的作用一样)
 * 不断从ReferenceQueue中remove Tracker 实例(Tracker是一个PhantomReference的子类)
 * 然后尝试进行最后的清理工作
 */
public class SocketCleaningTracker {


    private static final ReferenceQueue<Object> queue = new ReferenceQueue<>();

    static {
        new Cleaner().start();
    }

    private static void track(Socket socket) {
        new Tracker(socket, queue);
    }

    private static class Cleaner extends Thread {

        private Cleaner() {
            setDaemon(true);
        }

        @Override
        public void run() {
            for (; ; ) {
                try {
                    // 当Tracker被垃圾回收器回收时会加入queue中
                    Tracker tracker = (Tracker) queue.remove();
                    tracker.close();
                } catch (InterruptedException e) {

                }
            }
        }
    }

    private static class Tracker extends PhantomReference<Object> {

        private final Socket socket;

        Tracker(Socket socket, ReferenceQueue<? super Object> q) {
            super(socket, q);
            this.socket = socket;
        }

        public void close() {
            try {
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

ReferenceQueue

使用ReferenceQueue清除失去了引用对象的SoftReference或者WeakReference,
从ReferenceQueue这个名字也可以看出,它是一个队列,当我们调用它的poll()方法的时候,如果这个队列中不是空队列,那么将返回队列前面的那个Reference对象。
在任何时候,我们都可以调用ReferenceQueue的poll()方法来检查是否有它所关心的非强可及对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个非強Reference对象。利用这个方法,我们可以检查哪个非強Reference所引用的对象已经被回收。于是我们可以把这些失去所引用的对象的非強Reference对象清除掉

 private static void testReferenceQueue() throws InterruptedException {
        /**
         * 被垃圾回收的Reference会被加入与之关联的Queue中
         */
        ReferenceQueue<Reference> queue = new ReferenceQueue<>();
        Reference ref = new Reference();
        WeakReference<Reference> weakReference = new WeakReference<>(ref, queue);
        ref = null;
        System.out.println("before gc: " + weakReference.get());
        System.gc();
        // make sure GC thread triggered.
        TimeUnit.SECONDS.sleep(1);
        System.out.println("after gc: " + weakReference.get());

        java.lang.ref.Reference<? extends Reference> gcRef = queue.remove();
        /**
         * 被垃圾回收后,可以从队列中获得
         */
        System.out.println("gcRef: " + gcRef);
        System.out.println("gcRef get(): " + gcRef.get());

        /**
         * jdk11.0.9_11\bin\java.exe -Xmx64M -Xms64M -XX:+PrintGCDetails
         * [0.004s][warning][gc] -XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead.
         * [0.014s][info   ][gc,heap] Heap region size: 1M
         * [0.016s][info   ][gc     ] Using G1
         * [0.016s][info   ][gc,heap,coops] Heap address: 0x00000000fc000000, size: 64 MB, Compressed Oops mode: 32-bit
         * before gc: com.james.example.thread.jcp_multithread_architecture.chapter25.ReferenceTest$Reference@1cd072a9
         * [0.136s][info   ][gc,task      ] GC(0) Using 2 workers of 10 for full compaction
         * [0.136s][info   ][gc,start     ] GC(0) Pause Full (System.gc())
         * [0.136s][info   ][gc,phases,start] GC(0) Phase 1: Mark live objects
         * [0.138s][info   ][gc,stringtable ] GC(0) Cleaned string and symbol table, strings: 2913 processed, 3 removed, symbols: 26556 processed, 0 removed
         * [0.138s][info   ][gc,phases      ] GC(0) Phase 1: Mark live objects 1.531ms
         * [0.138s][info   ][gc,phases,start] GC(0) Phase 2: Prepare for compaction
         * [0.138s][info   ][gc,phases      ] GC(0) Phase 2: Prepare for compaction 0.292ms
         * [0.138s][info   ][gc,phases,start] GC(0) Phase 3: Adjust pointers
         * [0.138s][info   ][gc,phases      ] GC(0) Phase 3: Adjust pointers 0.508ms
         * [0.138s][info   ][gc,phases,start] GC(0) Phase 4: Compact heap
         * [0.139s][info   ][gc,phases      ] GC(0) Phase 4: Compact heap 0.545ms
         * [0.139s][info   ][gc,heap        ] GC(0) Eden regions: 4->0(23)
         * [0.139s][info   ][gc,heap        ] GC(0) Survivor regions: 0->0(0)
         * [0.139s][info   ][gc,heap        ] GC(0) Old regions: 0->2
         * [0.139s][info   ][gc,heap        ] GC(0) Humongous regions: 11->11
         * [0.139s][info   ][gc,metaspace   ] GC(0) Metaspace: 6359K->6359K(1056768K)
         * [0.139s][info   ][gc             ] GC(0) Pause Full (System.gc()) 14M->11M(64M) 3.194ms
         * [0.139s][info   ][gc,cpu         ] GC(0) User=0.00s Sys=0.00s Real=0.00s
         * the reference will be GC
         * after gc: null
         * gcRef: java.lang.ref.WeakReference@7c75222b
         * gcRef get(): null
         * [1.140s][info   ][gc,heap,exit   ] Heap
         * [1.140s][info   ][gc,heap,exit   ]  garbage-first heap   total 65536K, used 14274K [0x00000000fc000000, 0x0000000100000000)
         * [1.140s][info   ][gc,heap,exit   ]   region size 1024K, 3 young (3072K), 0 survivors (0K)
         * [1.140s][info   ][gc,heap,exit   ]  Metaspace       used 7330K, capacity 7397K, committed 7680K, reserved 1056768K
         * [1.140s][info   ][gc,heap,exit   ]   class space    used 652K, capacity 672K, committed 768K, reserved 1048576K
         */}

Reference



    public class Reference {
        //10M
        private final byte[] data = new byte[1024 * 1024 * 10];

        protected void finalize() throws Exception {
            System.out.println("the reference will be GC");
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值