java中的四种引用——强、软、弱、虚

简介: java中的四种引用——强、软、弱、虚

一、强引用


强引用比较好理解,我们编程中绝大部分对象都是强引用,在GC过程中,如果存在强引用对象,即便发生OOM,也不会被回收

Object m = new Object();


image.png


二、软引用


在堆内存不足时,jvm的GC会回收软引用对象

public class SoftReferenceTest {
    public static void main(String[] args) {
        SoftReference<byte[]> m = new SoftReference<>(new byte[1024 * 1024 * 10]);
        System.out.println(m.get());
        System.gc();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(m.get());
        byte[] b = new byte[1024 * 1024 * 15];
        System.out.println(m.get());
    }
}


上述代码在内存中的引用关系如下图所示


image.png


假如我们指定-Xmx20M,然后运行

[B@2503dbd3
[B@2503dbd3
null


从运行结果可以看出,第一次和第二次输入对象不为空,即便中间发生了一次gc,第二次依然不为空,是因为内存足够,所以不会被回收,但是当第三次new一个15M的对象时,总空间15+10=25M,超出堆内存总大小(20M),这时jvm会回收调软引用对象。

软引用的使用场景:缓存(比如缓存一些图片文件)


三、弱引用


把上面代码稍作修改,将软引用改为弱引用,其他保持不变

public class WeakReferenceTest {
    public static void main(String[] args) {
        WeakReference<byte[]> m = new WeakReference<>(new byte[1024 * 1024 * 10]);
        System.out.println(m.get());
        System.gc();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(m.get());
        byte[] b = new byte[1024 * 1024 * 15];
        System.out.println(m.get());
    }
}


image.png


运行结果

[B@2503dbd3
null
null


从运行结果可以看出,第二次输出时,即便内存足够,依然会被回收。


结论:垃圾回收器会直接回收弱引用对象,和软引用的区别就是不管内存是否充裕都会被回收。


ThreadLocal就是用到了弱引用技术,关于ThreadLocal可以参见另一篇博文


ThreadLocal


四、虚引用


public class PhantomReferenceTest {
    private static final List<Object> LIST = new LinkedList<>();
    private static final ReferenceQueue<M> QUEUE = new ReferenceQueue<>();
    public static void main(String[] args) {
        PhantomReference<M> pr = new PhantomReference<>(new M(), QUEUE);
        //虚引用输出为空
        System.out.println(pr.get());
    }
}


java官方的解释:


Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.


虚引用指向的对象有可能会被重新访问到,常用于对象死亡后的清理操作。


image.png


在NIO场景中,堆内存中的对象有可能会访问堆外内存的对象,当堆内存被GC回收时,堆外内存也应该释放,JVM是怎么知道堆外内存是否可回收呢,所以java提供了一种钩子机制,这种机制就是虚引用。


应用场景:管理直接内存(堆外内存)


相关文章
|
5月前
|
安全 Java
从零开始学习 Java:简单易懂的入门指南之不可变集合、方法引用(二十六)
从零开始学习 Java:简单易懂的入门指南之不可变集合、方法引用(二十六)
|
4月前
|
缓存 Java 数据库连接
java面试题目 强引用、软引用、弱引用、幻象引用有什么区别?具体使用场景是什么?
【6月更文挑战第28天】在 Java 中,理解和正确使用各种引用类型(强引用、软引用、弱引用、幻象引用)对有效的内存管理和垃圾回收至关重要。下面我们详细解读这些引用类型的区别及其具体使用场景。
59 3
|
3月前
|
Java 运维
开发与运维引用问题之软引用又在Java特点如何解决
开发与运维引用问题之软引用又在Java特点如何解决
38 0
|
4月前
|
Java
java方法引用::
java方法引用::
|
5月前
|
存储 Java
滚雪球学Java(41):Lambda表达式和方法引用:提高代码可读性和简洁性的神器
【5月更文挑战第16天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
50 2
滚雪球学Java(41):Lambda表达式和方法引用:提高代码可读性和简洁性的神器
|
5月前
|
存储 Java 索引
Java一维数组元素的引用与操作技术详解
Java一维数组元素的引用与操作技术详解
53 1
|
5月前
|
Java
【JAVA学习之路 | 进阶篇】方法引用与构造器引用
【JAVA学习之路 | 进阶篇】方法引用与构造器引用
|
5月前
|
存储 Java 索引
Java的数组定义与引用
Java的数组定义与引用
|
5月前
|
存储 Java 索引
Java二维数组的引用与操作技术详解
Java二维数组的引用与操作技术详解
68 0
|
5月前
|
缓存 Java
【JAVA】强引用、软引用、弱引用、幻象引用有什么区别?
幻象引用:幻象引用是最弱的引用类型,几乎不影响对象的生命周期。它们主要用于在对象被回收前进行某些预处理操作,例如在对象被销毁时执行特定的清理任务。
50 0