JVM - 【GC】四种引用类型

Java四种引用类型

  • 强引用(StrongReference)
  • 软引用(SoftReference)
  • 弱引用(WeakReference)
  • 虚引用(PhantomReference)

一:继承关系图(JDK1.2

JVM - 【GC】四种引用类型_第1张图片

二:强引用(StrongReference

不可被回收

package xyz.xx.chapter2;

/**
 * -XX:+PrintGCDetails
 *
 * 强引用如果为可触及状态不会被GC回收
 */
public class StrongReferenceTest1 {
     
    public static void main(String[] args) {
     
        Obj o1 = new Obj();
        Obj o2 = o1;

        o1 = null;
        System.gc();

        System.out.println(o2);
    }
}

class Obj{
     
    byte[] bys = new byte[1024*1024*20];
}

三:软引用(SoftReference

OOM时会被回收

package xyz.xx.chapter2;

import java.lang.ref.SoftReference;

/**
 *  -XX:+PrintGCDetails -Xms40m -Xmx40m
 *
 *  软引用会在OOM时前执行的GC时释放
 */
public class SoftReferenceTest1 {
     
    public static void main(String[] args) {
     
        // 创建一个软引用对象(方式一)
        // SoftReference sr1 = new SoftReference<>(new Obj());

        // 创建一个软引用对象(方式二)
        Obj o1 = new Obj();
        SoftReference<Obj> sr2 = new SoftReference<>(o1);
        o1 = null;

        Obj o2 = new Obj();

        System.out.println(sr2.get());
    }
}

四:弱引用(WeakReference

GC执行就会被回收、发现即回收

package xyz.xx.chapter2;

import java.lang.ref.WeakReference;

/**
 * -XX:+PrintGCDetails
 *
 * 弱引用会在每一次GC时被释放
 */
public class WeakReferenceTest1 {
     
    public static void main(String[] args) {
     
        // 创建弱引用对象(方式一)
        // WeakReference wr1 = new WeakReference<>(new Obj());

        // 创建弱引用对象(方式二)
        Obj o1 = new Obj();
        WeakReference<Obj> wr2 = new WeakReference<>(o1);
        o1 = null;

        System.out.println("回收前");
        System.out.println(wr2.get());
        System.gc();
        System.out.println("回收后");
        System.out.println(wr2.get());
    }
}

五:虚引用(PhantomReference)

  • 用于跟踪对象被回收过程
  • 与ReferenceQueu配合使用
  • 后台可开启Deamon Thread监控垃圾回收过程

JVM - 【GC】四种引用类型_第2张图片

package xyz.xx.chapter2;

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

/**
 * 虚引用测试
 *      1. 测试finalize的特性
 *          只调用一次
 *          在GC前会被调用
 *      2. 使用后台进行进行后台监控
 *
 *
 *  尝试从PhantomReference中获取对象:null
 *  第一次回收
 *  [我快要被回收了!]
 *  PhantomReferenceTest1{}
 *  第二次回收
 *  [垃圾回收监控线程] PhantomReferenceTest1实例被GC回收了!
 *  obj是null
 */
public class PhantomReferenceTest1 {
     

    public static PhantomReferenceTest1 obj;
    public static ReferenceQueue<PhantomReferenceTest1> phantomQueue;

    public static class CheckReference extends Thread{
     
        @Override
        public void run() {
     
            super.run();
            while(true){
     
                if(phantomQueue != null){
     
                    PhantomReference<PhantomReferenceTest1> tempObj = null;
                    try {
     
                        tempObj = (PhantomReference<PhantomReferenceTest1>)phantomQueue.remove();
                    } catch (InterruptedException e) {
     
                        e.printStackTrace();
                    }
                    if(tempObj!=null){
     
                        System.out.println("[垃圾回收监控线程] PhantomReferenceTest1实例被GC回收了!");
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
     
        // 启动线程
        CheckReference checkReferenceThread = new CheckReference();
        // 设置为守护线程
        // 守护线程
        //      1. 在后台处理
        //      2. 当程序中只剩下守护线程时(Daemon Thread),守护线程会自动结束
        checkReferenceThread.setDaemon(true);
        checkReferenceThread.start();


        obj = new PhantomReferenceTest1();
        phantomQueue = new ReferenceQueue<>();
        PhantomReference<PhantomReferenceTest1> pr = new PhantomReference<>(obj,phantomQueue);

        // 尝试从虚引用对象中获取指定对象
        System.out.println("尝试从PhantomReference中获取对象:"+pr.get());

        obj = null;
        System.gc();
        System.out.println("第一次回收");
        try {
     
            Thread.sleep(1000);
        } catch (InterruptedException e) {
     
            e.printStackTrace();
        }
        if(obj==null){
     
            System.out.println("obj是null");
        }else{
     
            System.out.println(obj);
        }
        obj = null;
        System.gc();
        System.out.println("第二次回收");
        try {
     
            Thread.sleep(1000);
        } catch (InterruptedException e) {
     
            e.printStackTrace();
        }
        if(obj==null){
     
            System.out.println("obj是null");
        }else{
     
            System.out.println(obj);
        }

    }

    @Override
    protected void finalize() throws Throwable {
     
        super.finalize();
        System.out.println("[我快要被回收了!]");
        obj = this;
    }

    @Override
    public String toString() {
     
        return "PhantomReferenceTest1{}";
    }
}

你可能感兴趣的:(JVM,java,jvm,四种引用,引用)