-
强引用、软引用、弱引用、虚引用得区别和作用,以及例子
2020-11-29 00:20:45引用大佬的博客: Java:强引用,软引用,弱引用和虚引用 建议直接看大佬的博客,我这里只做总结。 总结 强引用 相当于 Object obj=new Object()这种引用就是强引用,即使OOM也不会被垃圾回收器进行回收 软引用 如果...引用大佬的博客: Java:强引用,软引用,弱引用和虚引用
建议直接看大佬的博客,我这里只做总结。
总结
强引用 相当于
Object obj=new Object()
这种引用就是强引用,即使OOM也不会被垃圾回收器进行回收
软引用 如果将要发生了OOM(内存不够用了)则会将对象自动回收
弱引用 只要发生了gc()
就会进行回收虚引用的对象
虚引用 主要用来跟踪对象被垃圾回收的活动。虚引用必须和引用队列关联使用。案例:
import java.lang.ref.*; public class WeakReferenceDemo { public static void main(String[] args) { softReferenceTest();// 软引用 weakReferenceTest();// 弱引用 } /** * 软引用测试案例 * 会发现gc后软引用还能获取"hello world!!!",只有将要OOM的gc才会回收对象那么返回null */ private static void softReferenceTest() { String helloWorldString = new String("hello world!!!"); // 在堆中根据常量字符串创建一个新的字符串对象 SoftReference<String> stringSoftReference = new SoftReference<>(helloWorldString); System.out.println("打印一下软引用的字符串:" + stringSoftReference.get());//没有进行gc前软引用能得到对象 /** * 置 null 的作用 * 去除helloWorldString强引用字符串"hello world!!!", * 因为对象一旦被强引用指向,即使内存不够,宁愿报错也不会被回收改对象,相当于"hello world!!!"原先由两个引用指向这个对象 */ helloWorldString = null; System.gc();//进行垃圾回收 stringSoftReference.get(); System.out.println("软引用的字符串被垃圾回收了,得到的字符串是:" + stringSoftReference.get()); } /** * 弱引用测试案例 * 会发现gc后,弱引用不能获取"hello world!!!" */ private static void weakReferenceTest() { String helloWorldString = new String("hello world!!!"); // 在堆中根据常量字符串创建一个新的字符串对象 WeakReference<String> stringWeakReference = new WeakReference<>(helloWorldString);// 创建一个弱引用,将弱引用指向堆中的那个字符串 /** * 置 null 的作用 * 去除helloWorldString强引用字符串"hello world!!!", * 因为对象一旦被强引用指向,即使内存不够,宁愿报错也不会被回收改对象,相当于"hello world!!!"原先由两个引用指向这个对象 */ helloWorldString = null; System.out.println("打印一下弱引用的字符串:" + stringWeakReference.get());//没有进行gc前软引用能得到对象 System.gc();//进行垃圾回收 stringWeakReference.get(); System.out.println("弱引用的字符串被垃圾回收了,得到的字符串是:" + stringWeakReference.get()); } }
再度总结
之所以要分成这四种引用,就是在gc的时候被引用的对象是否会被回收内存所分成的情况,以及考虑发生OOM的情况进行gc
强引用: 不用举例子,平时new引用的对象就是强引用
软引用: 可以通过SoftReference<Obj> sr = new SoftReference<Obj>(obj);
进行引用,
弱引用: 通过WeakReference<String> sr = new WeakReference<String>(new String("hello"));
这个例子使用new创建对象为了避免对象在常量池中。
虚引用: 主要用来跟踪对象被垃圾回收的活动(GCRoot中的引用链应该就是用这个做的,如果一个对象没有被引用GCRoot引用到,则说明这是一个内存垃圾,需要进行垃圾回收)
虚引用的使用例子:
ReferenceQueue<String> queue = new ReferenceQueue<String>(); PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);
-
强引用 软引用 弱引用 虚引用 引用队列
2020-06-30 13:48:00只要强引用还存在 垃圾回收器永远不会回收被强引用 引用的对象 如果强引用为null 或者已经超过了引用的作用范围对象就会被回收 2.软引用 如果当前对象没有强引用引用 在垃圾回收后的内存不够了 就会回收软引用连接...jvm的四种引用都有什么
1.强引用
FinalReference
一般像new Object()这类的引用
只要强引用还存在 垃圾回收器永远不会回收被强引用 引用的对象
如果强引用为null 或者已经超过了引用的作用范围对象就会被回收
2.软引用
如果当前对象没有强引用引用 在垃圾回收后的内存不够了 就会回收软引用连接的对象。
通过SoftReference类
实现。软引用可以和一个引用队列(ReferenceQueue)
联合使用,如果软引用所引用的对象
被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列
中。后续,我们可以调用ReferenceQueue的poll()方法来检查是否有它所关心的对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。Object obj = new Object(); SoftReference<Object> sf = new SoftReference<Object>(obj); obj = null; sf.get(); 通过sf.get()方法可以取得软引用所引用的对象 当对象被标记为需要回收的对象时, 则返回null;
3.弱引用
每一次的垃圾回收都会将弱引用连接的对象回收 无论内存是否够用
WeakReference类
实现
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象
被垃圾回收,Java虚拟机就会把这个弱引用
加入到与之关联的引用队列
中在静态内部类中,经常会使用虚引用。例如,一个类发送网络请求,承担callback的静态内部类,则常以虚引用的方式来保存外部类(宿主类)的引用,当外部类需要被JVM回收时,不会因为网络请求没有及时回来,导致外部类不能被回收,引起内存泄漏
Object obj = new Object(); WeakReference<Object> wf = new WeakReference<Object>(obj); obj = null; wf.get();//有时候会返回null wf.isEnQueued();//返回是否被垃圾回收器标记为即将回收的垃圾
4.虚引用
PhantomReference
无法通过虚引用访问对象的任何属性或函数
把一个对象设置虚引用的唯一作用就是当这个对象被回收的时候得到一个通知应用场景:可用来跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾收集器回收之前会收到一条系统通知。
幻象引用仅仅是提供了一种确保对象被 fnalize 以后,做某些事情的机制。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。ReferenceQueue queue = new ReferenceQueue ();PhantomReference pr = new PhantomReference (object, queue); 程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取一些程序行动
Object obj = new Object(); PhantomReference<Object> pf = new PhantomReference<Object>(obj); obj=null; pf.get();永远返回null pf.isEnQueued();返回是否从内存中已经删除
你能说一下软引用的应用场景么
对于不重要的资源 使用软引用,有内存就缓存 没有就删除。
首先把软引用相连对象删除 ,最后把软引用对象也删除
。
例子:图片缓存框架
中,“内存缓存”中的图片是以这种引用来保存,使得JVM在发生OOM之前,可以回收这部分缓存
在网络中读取的图片放到list中 进行查看
当前是new Object()是强引用
场景
:向list中存入在网上读取的4M的图片 设置当前堆内存为20M 存5次读取的图片
目标
:希望不占用内存 以后再读的时候再更新添加 而不是一直有一个byte[]
list和SoftReference SoftReference和byte[]数组是软引用
当垃圾回收器回收发现内存不够的时候就会把 软引用关联的对象byte[]删除 最后吧list也删除
当再去取的时候发现只有最后一个被保留下来了 原因是在第3,4次循环的时候发现循环不够就把软引用引用的对象删除了 引用就会进入到引用队列当中
下面来删除软引用本身 借助引用队列来删除软引用对象本身
4个null的软引用已经没了 -
强引用 软引用 弱引用 幻想引用
2018-12-24 14:23:40强引用:普通的创建对象构造的就是强引用关系,直到对象生命周期结束,或者显示赋值为null,这时候表明对象可以被回收了。 软引用:软引用相对强引用比较弱一些,可以豁免一些jvm的垃圾回收,当jvm认为空间不足时会...对象的引用关系关联到对象是否可被回收机回收策略。
- 强引用:普通的创建对象构造的就是强引用关系,直到对象生命周期结束,或者显示赋值为null,这时候表明对象可以被回收了。
- 软引用:软引用相对强引用比较弱一些,可以豁免一些jvm的垃圾回收,当jvm认为空间不足时会回收软引用。即确保OOM之前软引用会被回收,可以实现一些敏感的缓存。内存空闲时,缓存存在,内存不足时回收。
- 弱引用 : 此引用不能豁免垃圾回收,提供了一种弱引用状态下对象的访问。这是一种没有强制关系的引用,对象存在则返回不存在则重新实例化。
- 幻想引用:不能提供对象的访问,只是用来对象呗finalize后处理一些事情。
- 对象的引用和垃圾收集息息相关:
- 强可达:通过强引用引用的对象就是强可达。
- 软可达:通过软引用可以访问的对象。
- 弱可达:通过弱引用可以访问。
- 幻象可达:对象finalize后就是幻象引用。
- 之后就是不可达。
参考:java36讲
-
很详细的强引用、软引用、弱引用、虚引用-他们的特点及应用场景
2020-10-26 18:21:20强引用 强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfM moryError错误,使程序异常终止,也不会靠随意回收具有强引用 对象来解决内存不足...- 强引用
强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出
OutOfM moryError
错误,使程序异常终止,也不会靠随意回收具有强引用 对象来解决内存不足的问题。- 软引用
软引用是用来描述一些还有用但并非必须的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。
/** * 软引用何时被收集 * 运行参数 -Xmx200m -XX:+PrintGC * Created by ccr at 2018/7/14. */ public class SoftReferenceDemo { public static void main(String[] args) throws InterruptedException { //100M的缓存数据 byte[] cacheData = new byte[100 * 1024 * 1024]; //将缓存数据用软引用持有 SoftReference<byte[]> cacheRef = new SoftReference<>(cacheData); //将缓存数据的强引用去除 cacheData = null; System.out.println("第一次GC前" + cacheData); System.out.println("第一次GC前" + cacheRef.get()); //进行一次GC后查看对象的回收情况 System.gc(); //等待GC Thread.sleep(500); System.out.println("第一次GC后" + cacheData); System.out.println("第一次GC后" + cacheRef.get()); //在分配一个120M的对象,看看缓存对象的回收情况 byte[] newData = new byte[120 * 1024 * 1024]; System.out.println("分配后" + cacheData); System.out.println("分配后" + cacheRef.get()); } } 第一次GC前null 第一次GC前[B@7d4991ad [GC (System.gc()) 105728K->103248K(175104K), 0.0009623 secs] [Full GC (System.gc()) 103248K->103139K(175104K), 0.0049909 secs] 第一次GC后null 第一次GC后[B@7d4991ad [GC (Allocation Failure) 103805K->103171K(175104K), 0.0027889 secs] [GC (Allocation Failure) 103171K->103171K(175104K), 0.0016018 secs] [Full GC (Allocation Failure) 103171K->103136K(175104K), 0.0089988 secs] [GC (Allocation Failure) 103136K->103136K(199680K), 0.0009408 secs] [Full GC (Allocation Failure) 103136K->719K(128512K), 0.0082685 secs] 分配后null 分配后null
从上面的示例中就能看出,软引用关联的对象不会被
GC
回收。JVM
在分配空间时,若果Heap
空间不足,就会进行相应的GC
,但是这次GC
并不会收集软引用关联的对象,但是在JVM发现就算进行了一次回收后还是不足(Allocation Failure
),JVM
会尝试第二次GC
,回收软引用关联的对象。像这种如果内存充足,
GC
时就保留,内存不够,GC
再来收集的功能很适合用在缓存的引用场景中。在使用缓存时有一个原则,如果缓存中有就从缓存获取,如果没有就从数据库中获取,缓存的存在是为了加快计算速度,如果因为缓存导致了内存不足进而整个程序崩溃,那就得不偿失了。- 弱引用
弱引用也是用来描述非必须对象的,他的强度比软引用更弱一些,被弱引用关联的对象,在垃圾回收时,如果这个对象只被弱引用关联(没有任何强引用关联他),那么这个对象就会被回收。
/** * 弱引用关联对象何时被回收 * Created by ccr at 2018/7/14. */ public class WeakReferenceDemo { public static void main(String[] args) throws InterruptedException { //100M的缓存数据 byte[] cacheData = new byte[100 * 1024 * 1024]; //将缓存数据用软引用持有 WeakReference<byte[]> cacheRef = new WeakReference<>(cacheData); System.out.println("第一次GC前" + cacheData); System.out.println("第一次GC前" + cacheRef.get()); //进行一次GC后查看对象的回收情况 System.gc(); //等待GC Thread.sleep(500); System.out.println("第一次GC后" + cacheData); System.out.println("第一次GC后" + cacheRef.get()); //将缓存数据的强引用去除 cacheData = null; System.gc(); //等待GC Thread.sleep(500); System.out.println("第二次GC后" + cacheData); System.out.println("第二次GC后" + cacheRef.get()); } } 第一次GC前[B@7d4991ad 第一次GC前[B@7d4991ad 第一次GC后[B@7d4991ad 第一次GC后[B@7d4991ad 第二次GC后null 第二次GC后null
从上面的代码中可以看出,弱引用关联的对象是否回收取决于这个对象有没有其他强引用指向它。这个确实很难理解,既然弱引用关联对象的存活周期和强引用差不多,那直接用强引用好了,干嘛费用弄出个弱引用呢?其实弱引用存在必然有他的应用场景。
static Map<Object,Object> container = new HashMap<>(); public static void putToContainer(Object key,Object value){ container.put(key,value); } public static void main(String[] args) { //某个类中有这样一段代码 Object key = new Object(); Object value = new Object(); putToContainer(key,value); //.......... /** * 若干调用层次后程序员发现这个key指向的对象没有用了, * 为了节省内存打算把这个对象抛弃,然而下面这个方式真的能把对象回收掉吗? * 由于container对象中包含了这个对象的引用,所以这个对象不能按照程序员的意向进行回收. * 并且由于在程序中的任何部分没有再出现这个键,所以,这个键 / 值 对无法从映射中删除。 * 很可能会造成内存泄漏。 */ key = null; }
下面一段话摘自《Java核心技术卷1》:
设计
WeakHashMap
类是为了解决一个有趣的问题。如果有一个值,对应的键已经不再 使用了, 将会出现什么情况呢? 假定对某个键的最后一次引用已经消亡,不再有任何途径引 用这个值的对象了。但是,由于在程序中的任何部分没有再出现这个键,所以,这个键 / 值 对无法从映射中删除。为什么垃圾回收器不能够删除它呢? 难道删除无用的对象不是垃圾回 收器的工作吗?遗憾的是,事情没有这样简单。垃圾回收器跟踪活动的对象。只要映射对象是活动的, 其中的所有桶也是活动的, 它们不能被回收。因此,需要由程序负责从长期存活的映射表中 删除那些无用的值。 或者使用
WeakHashMap
完成这件事情。当对键的唯一引用来自散列条
目时, 这一数据结构将与垃圾回收器协同工作一起删除键 / 值对。下面是这种机制的内部运行情况。
WeakHashMap
使用弱引用(weak references
) 保存键。WeakReference
对象将引用保存到另外一个对象中,在这里,就是散列键。对于这种类型的 对象,垃圾回收器用一种特有的方式进行处理。通常,如果垃圾回收器发现某个特定的对象 已经没有他人引用了,就将其回收。然而, 如果某个对象只能由WeakReference
引用, 垃圾 回收器仍然回收它,但要将引用这个对象的弱引用放人队列中。WeakHashMap
将周期性地检 查队列, 以便找出新添加的弱引用。一个弱引用进人队列意味着这个键不再被他人使用, 并 且已经被收集起来。于是,WeakHashMap
将删除对应的条目。除了
WeakHashMap
使用了弱引用,ThreadLocal
类中也是用了弱引用。- 虚引用
一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来获取一个对象的实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。虚引用和弱引用对关联对象的回收都不会产生影响,如果只有虚引用活着弱引用关联着对象,那么这个对象就会被回收。它们的不同之处在于弱引用的
get
方法,虚引用的get
方法始终返回null
,弱引用可以使用ReferenceQueue
,虚引用必须配合ReferenceQueue
使用。jdk
中直接内存的回收就用到虚引用,由于jvm
自动内存管理的范围是堆内存,而直接内存是在堆内存之外(其实是内存映射文件,自行去理解虚拟内存空间的相关概念),所以直接内存的分配和回收都是有Unsafe
类去操作,java
在申请一块直接内存之后,会在堆内存分配一个对象保存这个堆外内存的引用,这个对象被垃圾收集器管理,一旦这个对象被回收,相应的用户线程会收到通知并对直接内存进行清理工作。 -
强引用 软引用 弱引用 幻象引用
2018-08-17 20:12:17特点:我们平常典型编码 Object obj=new Object() 中的obj就是强引用。通过关键字new创建的对象所关联的引用就是强引用。当JVM内存不足时,JVM宁愿抛出OutofMemoryError运行时错误(OOM),使程序异常终止,也不会..... -
java强引用 软引用 弱引用 虚引用
2020-05-03 01:30:30所谓强引用(“Strong” Reference),就是我们最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还“活着”,垃圾收集器不会碰这种对象。对于一个普通的对象,如果没有其他的引用关系,只要超过了... -
强引用、软引用、弱引用、虚引用
2021-02-25 13:06:41强引用 强引用是默认支持,当内存不足的时候,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会回收对象。 强引用是最常见的普通对象引用,只要还有强引用指向对象,对象就存活,垃圾回收器不会处理存活... -
Java 四种引用 强引用 软引用 弱引用 虚引用
2019-03-04 11:16:101强引用 :只要引用存在,垃圾回收器就不会回收 大多是使用为强引用(比如new 对象,显示赋值等) 一个对象具有请引用,或者有强引用与之关联。JVM在内存不足时会抛出异常,不会回收对象。取消强引用,可以显示... -
Java引用类型:强引用,软引用,弱引用,虚引用
2018-10-23 19:29:34在Java中提供了4个级别的引用:强引用,软引用,弱引用,虚引用。在这4个引用级别中,只有强引用FinalReference类是包内可见,其他3中引用类型均为public,可以在应用程序中直接使用。 强引用 Java中的引用,有点像... -
强引用、软引用、弱引用、虚引用、引用队列
2020-07-11 18:31:11引用强度从高到低的顺序:强引用、软引用、弱引用、虚引用。 1、强引用 强引用就是我们平常最多使用的引用方式,比如 Student a = new Student(); Student b = a; 这两种形式都是强引用。 如果一个对象上有强引用... -
强引用,软引用,弱引用,虚引用
2020-05-27 20:26:46JDK1.2之后,Java对引用的概念进行了扩充,将引用分为强引用,软引用,弱引用,虚引用4种,这四种引用强度依次逐渐减弱,除了强引用外,其他三种引用类型都在java,lang包下,可直接使用 简单介绍下四种引用: 强... -
强引用、弱引用、软引用与虚引用
2019-08-13 20:15:15强引用、弱引用、软引用与虚引用强引用强引用的特点软引用弱引用虚引用:(PhantomReference)(对象回收和跟踪) 强引用 强引用指普通的对象引用 例如: StringBuffer str = new StringBuffer("hello world"); ... -
强引用和弱引用
2018-07-12 18:58:50强引用和弱引用 -
强引用、软引用、弱引用和幻想引用
2020-03-20 10:14:18强引用:对对象的直接的引用,一般的new创建对象,或者将一个对象赋值给一个引用类型就是强引用,强引用是最常见的,只要对象有还有强引用指向,那么对象就是"活着",GC并不会回收这些对象。而解除强引用可以把引用... -
Java对象引用-强软弱虚(强引用、软引用、弱引用、虚引用)
2020-10-18 00:30:02目录 (1)强引用 (2)软引用 (3)弱引用 (4)虚引用 ...强软弱虚(强引用、软引用、弱引用、虚引用)对应的是四种... * 强引用,常见的new对象是强引用 */ public class TestNormalReference { public stati.. -
强引用、软引用、弱引用
2020-06-29 23:33:041、强引用 一般使用的引用都是强引用,即 强引用的对象不会被垃圾回收器回收,即使内存不足抛出异常。 2、软引用 只有当内存不足是才会被垃圾回收器回收,使用java.lang.ref.SoftReference表示。 3、弱引用 ... -
强引用、软引用、弱引用和虚引用
2020-10-16 17:45:01所谓强引用(“Strong” Reference),就是我们最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还“活着”,垃圾收集器不会碰这种对象。对于一个普通的对象,如果没有其他的引用关系,只要超过了... -
强引用,弱引用,软引用
2019-02-21 11:04:51强引用是使用普遍的引用,如果一个对象具有强引用,那么java回收器不会被回收它,当内存不足时,java虚拟机宁愿抛出outOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象。如果这个强引用是作..... -
强引用,软引用,弱引用,幻象引用有什么区别?
2020-05-19 23:42:41强引用,软引用,弱引用,幻象引用有什么区别? 不同的引用类型,主要体现的是对象的不同的可达性(reachable)状态和对垃圾收集的影响。 所谓强引用 (Strong Reference) 就是我们常见的普通对象引用,只要还有强... -
四种引用 - 强引用、软引用、弱引用、虚引用
2020-08-30 14:03:421. 强引用 强引用:被引用关联的对象永远不会被垃圾收集器回收 Object object=new Object();那object就是一个强引用了。如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当... -
强引用 软引用 弱引用 虚引用
2018-04-27 00:15:481.概念解释强引用是使用最普遍的引用:Object o=new Object(); 特点:不会被GC将对象的引用显示地置为null:o=null; // 帮助垃圾收集器回收此对象举例ArrayList的实现源代码: 软引用用来描述一些还有用但是并非... -
强引用、弱引用、软引用和虚引用
2019-05-11 15:30:45划分几种引用类型目的: ...当内存空间不足时,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。 如果强引用对象不使用时,需要... -
四大引用——强引用、软引用、弱引用、虚引用
2019-03-11 10:26:02强引用、软引用、弱引用、虚引用强引用软引用弱引用虚引用 在JDK 1.2之后,Java对引用的概念进行了扩充,将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用... -
Java强引用,软引用,弱引用与虚引用
2020-05-28 17:25:50目录1 概述2 强引用(StrongReference)3 软引用(SoftReference)4 弱引用(WeakReference)5 虚引用 参考资料 深入理解 1 概述 引用类型 被回收时间 用途 生存时间 强引用 从来不会 对象的一般状态 JVM停止运行...