ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

强引用、软引用、弱引用、虚引用【转载】

2022-01-18 11:33:00  阅读:131  来源: 互联网

标签:对象 内存 回收 垃圾 JVM 转载 引用


https://blog.csdn.net/qq_39192827/article/details/85611873

我们希望一些对象,当内存还够是,则保留在内存中;如果内存不足,则可以抛弃这些对象,提出了四种引用类型。

Java中提供这四种引用类型主要有两个目的:第一是可以让程序员通过代码的方式决定某些对象的生命周期;第二是有利于JVM进行垃圾回收。

强引用:如果一个对象具有强引用,他不会被垃圾回收器回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象。
软引用:是用来描述一些有用但并不是必需的对象,只有在内存不足的时候JVM才会回收该对象
弱引用:用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象
虚引用:如果一个对象与虚引用关联,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收的活动。

一、强引用

实际中普遍使用的就是强引用。

Object object = new Object();
String str = "StrongReference";

如果一个对象具有强引用,他不会被垃圾回收器回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象。

如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象。

比如ArraryList类的clear方法中就是通过将引用赋值为null来实现清理工作的

public void clear() {
    modCount++;
​
    // Let gc do its work
    for (int i = 0; i < size; i++)
    elementData[i] = null;
    size = 0;
}

在ArrayList类中定义了一个私有的变量elementData数组,在调用方法清空数组时可以看到为每个数组内容赋值为null。不同于elementData=null,强引用仍然存在,避免在后续调用 add()等方法添加元素时进行重新的内存分配。使用如clear()方法中释放内存的方法对数组中存放的引用类型特别适用,这样就可以及时释放内存。

二、软引用

软引用是用来描述一些有用但并不是必需的对象,在Java中用java.lang.ref.SoftReference类来表示。对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象。因此,这一点可以很好地用来解决OOM的问题,并且这个特性很适合用来实现缓存:比如网页缓存、图片缓存等。

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列中。

import java.lang.ref.SoftReference;
​
    public class SoftRef { 
​
        public static void main(String[] args){ 
            System.out.println("start"); 
            Obj obj = new Obj(); 
            SoftReference<Obj> sr = new SoftReference<Obj>(obj); 
            obj = null; 
            System.out.println(sr.get()); 
            System.out.println("end"); 
        } 
    } 
​
    class Obj{ 
        int[] obj ; 
        public Obj(){ 
        obj = new int[1000]; 
    } 
}

当内存足够大时可以把数组存入软引用,取数据时就可从内存里取数据,提高运行效率

软引用在实际中有重要的应用:

  • 浏览器的后退按钮,这个后退时显示的网页内容可以重新进行请求或者从缓存中取出:

(1)如果一个网页在浏览结束时就进行内容的回收,则按后退查看前面浏览过的页面时,需要重新构建

(2)如果将浏览过的网页存储到内存中会造成内存的大量浪费,甚至会造成内存溢出这时候就可以使用软引用

  • 高速缓存就用到了软引用,有空闲内存,就可以暂时保留缓存,当内存不足时清理。这样保证了缓存的同时,不会耗尽内存

三、弱引用

弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用java.lang.ref.WeakReference类来表示。

弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。所以被软引用关联的对象只有在内存不足时才会被回收,而被弱引用关联的对象在JVM进行垃圾回收时总会被回收。

import java.lang.ref.WeakReference;
​
public class WeakRef {
    public static void main(String[] args) {
        //当要获得weak reference引用的object时, 首先需要判断它是否已经被回收,如果wr.get()方法为空, 那么说明weakCar指向的对象已经被回收了。
        WeakReference<String> sr = new WeakReference<String>(new String("hello"));
        System.out.println(sr.get());
        System.gc(); //通知JVM的gc进行垃圾回收
        System.out.println(sr.get());
    }
}

运行结果:

hello
null

在使用软引用和弱引用的时候,我们可以显示地通过System.gc()来通知JVM进行垃圾回收,但是要注意的是,虽然发出了通知,JVM不一定会立刻执行,也就是说这句是无法确保此时JVM一定会进行垃圾回收的。

弱引用还可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

应用场景:如果一个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么应该用 Weak Reference 来记住此对象。或者想引用一个对象,但是这个对象有自己的生命周期,你不想介入这个对象的生命周期,这时候就应该用弱引用,这个引用不会在对象的垃圾回收判断中产生任何附加的影响。

做二级缓存等。

四、虚引用

虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。在java中用java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收的活动。

虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
​
​
public class PhantomRef {
    public static void main(String[] args) {
        ReferenceQueue<String> queue = new ReferenceQueue<String>();
        PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);
        System.out.println(pr.get());
    }
}

 

标签:对象,内存,回收,垃圾,JVM,转载,引用
来源: https://www.cnblogs.com/windrose-sanyue/p/15817068.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有