Java基础实战:Java中的引用类型(强软弱虚)

下面是一个在下面引用实战中用到的公共类

public class M {
    @Override
    protected void finalize() throws Throwable{
        System.out.println("finalize");
    }
}

finalize()方法是执行gc时调用的方法。

一、强引用

  • 强引用是默认的引用类型。
  • 当一个对象具有强引用时,垃圾收集器不会回收该对象。
  • 只有在没有任何强引用指向一个对象时,该对象才会被垃圾收集器回收。
public class T01_NormalReference {
    public static void main(String[] args) throws IOException {
        M m = new M();
        m = null;
        System.gc();
        System.in.read();
    }
}

执行上面程序,结果如下。结果证明M被回收了。

二、软引用

  • 软引用用于描述一些还有用但不是必需的对象。
  • 当内存不足时,垃圾收集器会回收软引用指向的对象。
  • 可用于实现内存敏感的高速缓存。

软引用是一种用于描述一些还有用但不是必需的对象的引用类型,当内存不足时,垃圾收集器会回收软引用指向的对象。以下是一个验证软引用的示例代码:

public class T02_SoftReference {
    public static void main(String[] args) {
        SoftReference<byte[]> m = new SoftReference<>(new byte[1024*1024*10]);
        //m = null;
        System.out.println(m.get());
        System.gc();
        try {
            Thread.sleep(500);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println(m.get());
        // 模拟内存不足的情况
        try {
            // 分配大量内存,让系统触发垃圾回收
            byte[] memoryAlloc = new byte[1024 * 1024 * 15]; // 分配10MB的内存
        } catch (OutOfMemoryError e) {
            System.out.println("内存不足,系统触发了垃圾回收");
        }
        System.out.println(m.get());
    }
}

Java基础实战:Java中的引用类型(强软弱虚)_第1张图片
配置程序执行的最大内存为20M,执行结果如下
Java基础实战:Java中的引用类型(强软弱虚)_第2张图片
在这个示例中,我们首先创建一个字符串对象,并将其放入软引用中。然后,我们清空了强引用,使字符串对象只能被软引用引用。接下来,我们模拟了内存不足的情况,分配了大量内存,这将导致系统触发垃圾回收。最后,我们再次从软引用中获取对象,并检查对象是否被回收。

运行示例代码后,你会看到当内存不足时,垃圾收集器会回收软引用中的对象,软引用变为null,表示对象已被回收。这演示了软引用在内存管理中的作用。

三、弱引用

  • 弱引用用于描述非必需对象,但只要没有强引用指向它,就可能被垃圾收集器回收。
  • 通常用于构建对象注册表或管理器。

弱引用是Java中的一种引用类型,当对象只被弱引用引用时,垃圾收集器会在下一次垃圾回收时回收该对象。以下是一个验证弱引用的示例代码:

public class WeakReferenceExample {
    public static void main(String[] args) {
        // 创建一个字符串对象,并将其放入弱引用中
        String str = new String("这是一个弱引用示例");
        WeakReference<String> weakRef = new WeakReference<>(str);

        // 清空强引用,使字符串对象只被弱引用引用
        str = null;

        // 从弱引用中获取对象
        String retrieved = weakRef.get();

        // 打印从弱引用中获取的对象
        System.out.println("从弱引用中获取的对象:" + retrieved);

        // 模拟垃圾回收过程
        System.gc();

        // 等待一段时间以确保垃圾回收器完成回收
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 从弱引用中再次获取对象
        retrieved = weakRef.get();

        // 如果对象被回收,retrieved将为null
        if (retrieved == null) {
            System.out.println("对象已被回收");
        } else {
            System.out.println("对象仍然可用:" + retrieved);
        }
    }
}

运行上面程序,结果如下
Java基础实战:Java中的引用类型(强软弱虚)_第3张图片
在这个示例中,我们首先创建一个字符串对象,并将其放入弱引用中。然后,我们清空了强引用,使字符串对象只能被弱引用引用。接下来,我们获取弱引用中的对象,并打印出来。然后,我们模拟垃圾回收过程,并等待一段时间以确保垃圾回收器完成回收。最后,我们再次从弱引用中获取对象,并检查对象是否被回收。

运行示例代码后,你会看到当垃圾回收器执行后,弱引用中的对象被回收,因此再次从弱引用中获取的对象为null。这演示了弱引用的行为,它允许对象在没有强引用的情况下被垃圾收集。

四、虚引用

  • 虚引用是最弱的引用类型。
  • 它几乎不影响对象的生命周期,但允许在对象被回收前执行某些操作。
  • 通常与引用队列(ReferenceQueue)一起使用。
public class PhantomReferenceExample {
    public static void main(String[] args) {
        // 创建一个字符串对象,并将其放入虚引用中
        String str = new String("这是一个虚引用示例");
        ReferenceQueue<String> referenceQueue = new ReferenceQueue<>();
        PhantomReference<String> phantomRef = new PhantomReference<>(str, referenceQueue);

        // 清空强引用,使字符串对象只被虚引用引用
        str = null;

        // 从虚引用中获取对象
        String retrieved = phantomRef.get();

        // 获取虚引用的引用队列
        PhantomReference<String> before = (PhantomReference<String>) referenceQueue.poll();

        // 打印虚引用中的对象和引用队列
        System.out.println("从虚引用中获取的对象:" + retrieved);
        System.out.println("虚引用的引用队列:" + before);

        // 模拟垃圾回收过程
        System.gc();

        // 等待一段时间以确保垃圾回收器完成回收
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 检查引用队列,查看是否有虚引用对象被放入队列中
        PhantomReference<String> removedRef = (PhantomReference<String>) referenceQueue.poll();
        if (removedRef != null) {
            System.out.println("虚引用对象已被放入引用队列中");
            System.out.println("虚引用的引用队列:" + removedRef);
        } else {
            System.out.println("虚引用对象未被放入引用队列中");
        }
    }
}

运行上面程序,结果如下
Java基础实战:Java中的引用类型(强软弱虚)_第4张图片
在这个示例中,我们首先创建一个字符串对象,并将其放入虚引用中。然后,我们清空了强引用,使字符串对象只能被虚引用引用。接下来,我们获取虚引用中的对象,获取虚引用的引用队列,并模拟垃圾回收过程。最后,我们检查引用队列,查看是否有虚引用对象被放入队列中。

运行示例代码后,你会看到虚引用对象不可用(retrieved为null),并且虚引用对象已经被垃圾回收器回收并放入引用队列中。这演示了虚引用的行为,可以用于执行某些操作,例如清理相关资源,当对象被回收时。

你可能感兴趣的:(多线程&并发,Java基础,java,jvm,开发语言)