java中的强引用、软引用、弱引用、虚引用

简介: java中将引用类型分为强引用、软引用、弱引用、虚引用。之所以要这么划分,还是为了GC时更好的对对象进行处理。因为jvm已经明确了各种引用的GC方式,所以谈四种引用最好是和GC一起聊才会有意义(个人愚见)。

强引用、软引用、弱引用、虚引用



java中将引用类型分为强引用、软引用、弱引用、虚引用。之所以要这么划分,还是为了GC时更好的对对象进行处理。因为jvm已经明确了各种引用的GC方式,所以谈四种引用最好是和GC一起聊才会有意义(个人愚见)。


强引用


java中正常声明的变量都是强引用,比如:


String str = "Hello";
String stri = new String("Hello");


强引用只要是在栈空间仍存在指向堆中的引用就不会被回收。


怎么回收强引用?


1.类变量,声明过以后,在不使用时应做null处理。这样GC才会处理他,至于是不是下一次GC则不一定了。


2.局部变量,基本会在方法或者代码块执行完成之后就会GC,如果被其他变量引用了,仍存在引用链则不会回收。


软引用


软引用需要使用java提供的SoftReference来包装,如下则是软引用的声明方式:


String str = "abc";
SoftReference<String> sf = new SoftReference<String>(str);
String strRefe =  sf.get();
System.out.println(strRefe);
输出结果:
abc
Process finished with exit code 0


怎么回收软引用?


1.软引用会在jvm报OOM之前,将所有软引用全部清除,也就是说jvm内存吃紧会去清理软引用。


2.GC在回收软可达对象时,会回收软引用,回收这些软引用的对象时会判断该对象是不是不可达了,可达则不会回收。


举个例子证明内存紧张时软应用不会一定回收,因为这些对象仍是可达的:


public class TestHeapOom {
    static class OOMObject{
       String name;
       public OOMObject(String name){
           this.name = name;
       }
    }
    public static void main(String[] args){
        int n =0;
        List<OOMObject> list = new ArrayList<OOMObject>();
        SoftReference<List<OOMObject>> sr = new SoftReference<List<OOMObject>>(list);
        System.out.println(sr.get().size());
        while (true){
            list.add(new OOMObject("a"+n));
            System.out.println(sr.get().size());
        }
    }
}


程序输出:


1
1
...
106063
106064
106065
106066
106067
106068
106069
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
  at com.example.demo.OOM.TestHeapOom.main(TestHeapOom.java:34)
Process finished with exit code 1


输出结果解析:可以看到跑出的异常是“GC overhead limit exceeded”,该错误的意思是cpu98%时间在执行垃圾回收,但回收到的内存仍是非常小,会抛出该异常。如果这个程序不加软引用则抛出的是“Java heap space”,因为内存紧张程序就会试图回收软应用,则会一直运行GC,但是这些软应用仍是可达的,又回收不了,故会一直GC,却回收不到内存,就会有“GC overhead limit exceeded”这种异常。


弱引用


软引用需要使用java提供的WeakReference来包装,如下则是软引用的声明方式(此外java中的WearHashMap中的key默认就是弱引用,若是只有map引用这些对象,则会被回收):


WeakReference<String> wf = new WeakReference<String>(str);
String strRew = wf.get();
System.out.println(strRew);
输出结果:
abc
Process finished with exit code 0


怎么回收弱引用?


会在下一次gc时直接回收弱引用内存(不一定是一次gc就全部回收,且该对象必须是不可达才会回收,使用上面的例子仍然可以证明)


虚引用


软引用需要使用java提供的WeakReference来包装,虚引用是无法通过get得到值的,得到的永远会是null,如下则是软引用的声明方式:


ReferenceQueue rq = new ReferenceQueue();
PhantomReference<String> pf = new PhantomReference<String>(str,rq);
System.out.println(pf.get());


怎么回收虚引用?

虚引用会被直接回收,所以无法通过虚引用获得一个对象实例,但是被虚引用关联的对象何时回收其实不受任何影响,判断对象会不会回收依据仍然是jvm的可达性分析算法,为一个对象设置虚引用关联的唯一目的只是在这个对象被垃圾收集器回收时收到一个系统通知,判断虚引用关联的对象会不会回收仍然可用软引用中的例子。

————————————————

版权声明:本文为CSDN博主「归去来 兮」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/m0_46897923/article/details/109337874

相关文章
|
5月前
|
缓存 Java 程序员
Java面试题:解释强引用、软引用、弱引用和虚引用在Java中是如何工作的?
Java面试题:解释强引用、软引用、弱引用和虚引用在Java中是如何工作的?
40 1
|
6月前
|
缓存 Java 数据库连接
java面试题目 强引用、软引用、弱引用、幻象引用有什么区别?具体使用场景是什么?
【6月更文挑战第28天】在 Java 中,理解和正确使用各种引用类型(强引用、软引用、弱引用、幻象引用)对有效的内存管理和垃圾回收至关重要。下面我们详细解读这些引用类型的区别及其具体使用场景。
96 3
|
5月前
|
Java 运维
开发与运维引用问题之软引用又在Java特点如何解决
开发与运维引用问题之软引用又在Java特点如何解决
49 0
|
6月前
|
缓存 监控 算法
【Java】谈一谈虚引用
【Java】谈一谈虚引用
106 0
|
7月前
|
缓存 Java
【JAVA】强引用、软引用、弱引用、幻象引用有什么区别?
幻象引用:幻象引用是最弱的引用类型,几乎不影响对象的生命周期。它们主要用于在对象被回收前进行某些预处理操作,例如在对象被销毁时执行特定的清理任务。
64 0
|
7月前
|
Java
【JVM】深入理解Java引用类型:强引用、软引用、弱引用和虚引用
【JVM】深入理解Java引用类型:强引用、软引用、弱引用和虚引用
528 0
|
7月前
|
缓存 Java 程序员
Java垃圾回收: 什么是强引用、软引用、弱引用和虚引用?
Java垃圾回收: 什么是强引用、软引用、弱引用和虚引用?
79 2
|
算法 Java C++
14-理解Java中的不同引用类型:强引用、软引用、弱引用和虚引用
这篇文章将深入探讨Java中的四种引用类型:强引用、软引用、弱引用和虚引用。我们将逐一解释每种引用类型的特性和用途。
121 0
14-理解Java中的不同引用类型:强引用、软引用、弱引用和虚引用
|
Java C++
Java引用类型:强引用,软引用,弱引用,虚引用
Java引用类型:强引用,软引用,弱引用,虚引用
89 0
|
缓存 Java
【Java基础】java的引用类型(强引用,软引用,弱引用,虚引用)
【Java基础】java的引用类型(强引用,软引用,弱引用,虚引用)
154 0