Java 四种引用

目录

四种引用是怎么来的? 

SoftReference

 WeakReference

 PhantomReference


四种引用是怎么来的? 

        其实最开始的引用是用来判断一个对象是否存活的, 也就是说, 如果从GC Roots中的一个root出发, 如果存在一个引用链, 与这个对象有关联, 那么就说明这个对象是存活的. 

 但是有一点需要确认的是, 如果只是基于有没有被引用两种状态, 是不是过于狭隘了, 例如我们想要描述一些对象: 当空间足够的时候, 可以保留在内存之中, 如果内存不够了, 再将其进行垃圾回收, 其实很多场景就有这种需求. 

        在jdk1.2之中对引用的类型进行了扩充, 将引用扩充为了四个引用, 分别为: 

  • 强引用, 也就是直接new出来的引用, 例如 Object obj = new Object(); 只要这种强引用的关系存在, 那么 垃圾收集器就永远都不会收集它
  • 软引用, 这个用来描述那些非必须对象, 引用强度比软引用更弱一些.  被软引用关联的对象, 在系统发生内存溢出之前, 会把这类对象列进二次回收的范围之中, 如果回收之后, 还是没有足够的内存, 那么就会爆出内存溢出的异常. 
  • 弱引用, 描述那些非必须的, 缺了它也不会对系统造成什么影响, 被弱引用关联的对象, 只能生存到下一次垃圾回收之前, 无论是否内存足够, 都会被回收
  • 虚引用 , 最弱的一种引用关系, 一个对象是否有虚引用的存在, 完全不会对其生存时间构成影响, 也无法通过一个虚引用来获取一个实例对象, 唯一的目的就是为了能在被垃圾回收器回收的时候收到一个系统的通知

接下来我们来看看它们的api

SoftReference

import java.lang.ref.SoftReference;  
  
public class SoftReferenceExample {  
  
    // 使用 SoftReference 包装一个对象  
    private static class Cache<T> {  
        private final SoftReference<T> softRef;  
  
        public Cache(T object) {  
            this.softRef = new SoftReference<>(object);  
        }  
  
        public T get() {  
            return softRef.get();  
        }  
  
        public void set(T object) {  
            this.softRef = new SoftReference<>(object);  
        }  
    }  
  
    public static void main(String[] args) {  
        // 创建一个占用大量内存的对象,并包装在 SoftReference 中  
        byte[] largeArray = new byte[10 * 1024 * 1024]; // 10 MB  
        Cache<byte[]> cache = new Cache<>(largeArray);  
        largeArray = null; // 移除强引用  
  
        // 模拟一些操作  
        System.out.println("Initial Array: " + (cache.get() != null ? "Exists" : "Null"));  
  
        // 手动触发垃圾回收(通常不建议在生产环境中这样做)  
        System.gc();  
  
        // 此时 largeArray 应该仍然存在,因为内存还没有压力  
        System.out.println("After First GC: " + (cache.get() != null ? "Exists" : "Null"));  
  
        // 尝试分配大量内存以造成内存压力  
        byte[][] moreArrays = new byte[100][1024 * 1024]; // 100 MB  
  
        // 再次手动触发垃圾回收  
        System.gc();  
  
        // 此时 largeArray 可能会被回收,因为内存压力  
        System.out.println("After Memory Pressure and GC: " + (cache.get() != null ? "Exists" : "Null"));  
  
        // 释放 moreArrays 以减少内存压力  
        moreArrays = null;  
        System.gc();  
  
        // 如果此时 largeArray 被回收了,重新设置一个对象并测试  
        if (cache.get() == null) {  
            cache.set(new byte[10 * 1024 * 1024]); // 10 MB  
            System.out.println("Re-set Array: " + (cache.get() != null ? "Exists" : "Null"));  
        }  
    }  
}

 WeakReference

import java.lang.ref.WeakReference;  
  
public class WeakReferenceExample {  
  
    public static void main(String[] args) {  
        // 创建一个对象并通过 WeakReference 进行引用  
        String str = new String("Hello World");  
        WeakReference<String> weakRef = new WeakReference<>(str);  
  
        // 获取并打印被引用的对象  
        System.out.println("Weak reference value: " + weakRef.get());  
  
        // 清除强引用  
        str = null;  
  
        // 手动触发垃圾回收(通常不建议在生产环境中这样做)  
        System.gc();  
  
        // 尝试获取被引用的对象,此时应该为 null  
        System.out.println("Weak reference value after garbage collection: " + weakRef.get());  
    }  
}

 PhantomReference

        虚引用的get()方法始终返回null,因此无法通过虚引用来访问对象实例, 虚引用的工作机制主要依赖于ReferenceQueue。当一个对象被垃圾回收器确定为“不可达”(即所有强引用、软引用、弱引用都被清除),且它存在一个虚引用关联时,JVM会在回收该对象之前(或之后,具体取决于实现),将该虚引用插入到与之关联的ReferenceQueue中

import java.lang.ref.PhantomReference;  
import java.lang.ref.ReferenceQueue;  
  
public class PhantomReferenceExample {  
  
    public static void main(String[] args) {  
        // 创建一个对象  
        Object obj = new Object();  
  
        // 创建一个ReferenceQueue  
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();  
  
        // 创建一个PhantomReference  
        PhantomReference<Object> phantomRef = new PhantomReference<>(obj, referenceQueue);  
  
        // 清除强引用  
        obj = null;  
  
        // 手动触发垃圾回收(通常不建议在生产环境中这样做,这里仅用于测试)  
        System.gc();  
  
        // 等待垃圾回收器工作(这里使用简单的sleep来模拟等待,实际使用中应该避免这样做)  
        try {  
            Thread.sleep(1000);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
  
        // 检查ReferenceQueue中是否有虚引用被加入  
        PhantomReference<?> polledRef = (PhantomReference<?>) referenceQueue.poll();  
        if (polledRef != null && polledRef == phantomRef) {  
            // 执行清理操作  
            System.out.println("Object has been garbage collected, performing cleanup...");  
            // 注意:这里不能直接通过phantomRef.get()访问对象,因为get()方法始终返回null  
        } else {  
            System.out.println("Object has not been garbage collected yet.");  
        }  
    }  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值