文章目录

  • 一、 Java 引用类型 ( 强、软、弱、虚 )
  • 二、 软引用代码示例
  • 三、 弱引用代码示例

强引用 ( 不回收 ) > 软引用 ( OOM 前回收 ) > 弱引用 ( GC 必回收 ) > 虚引用 ( 回收前通知 )

如果单纯的想避免 OOM , 可以使用软引用 ;

如果对性能要求很高 , 要最大限度节省内存 , 所有的内存回收都要及时处理 , 就使用弱引用 ;

内存泄漏原理 : 长生命周期对象 , 持有短生命周期对象的引用 , 并且是强引用持有 , GC 无法释放该短生命周期对象引用 , 造成 OOM ;

一、 Java 引用类型 ( 强、软、弱、虚 )


1. 引用 :

① 变量引用 : 创建对象 , 将对象赋值给变量 VVV , 那么变量 VVV 就是对象的引用 ;

② 对象引用 : 对象 AAA 可以调用对象 BBB , 那么对象 AAA 持有对象 BBB 的引用 ;

2. 引用类型 : GC 垃圾回收机制 与 引用类型 密切相关 ;

① 强引用 : 最普遍的引用 , Object object = new Object() , 这就是强引用 ;

② 软引用 : 用于定义一些有用 , 但不是必须的对象 , 对象被软引用引用 , 当系统内存严重不足 , 在报出 OutOfMemoryError 错误之前就会将软件用释放掉 , 如果将软引用释放掉之后 , 还是内存不足 , 就会报 OutOfMemoryError 异常 ;

③ 弱引用 : 弱引用也是描述非必须对象 , 该引用的引用强度比软引用更弱 , 该引用对象 , 生命周期只到下一次 GC 回收之前 , GC 只要扫描到了弱引用 , 直接回收 , 即使内存足够 , 也要回收该对象所占用的内存 ;

④ 虚引用 : 虚引用无法获得被引用的对象 , 其唯一的作用是对象被回收时 , 可以得到相应的通知 ; 虚引用不会对对象的生存周期造成影响任何 , GC 忽略虚引用 , 即使有虚引用引用某对象 , GC 会当做该引用不存在 ; 开发时不常用 , 一般开发底层 SDK , 或监测系统运行类的软件时 , 才使用 ;

强引用 ( 不回收 ) > 软引用 ( OOM 前回收 ) > 弱引用 ( GC 必回收 ) > 虚引用 ( 回收前通知 )

二、 软引用代码示例


1. 软引用创建 :

① 直接创建软引用 : 在软件用构造函数中创建一个软引用 , 不涉及外部引用 ;

SoftReference<Object> softReference3 = new SoftReference<>(new Object());

② 传入创建好的对象引用创建软引用 : 软引用是通过在 软引用构造函数 传入引用对象创建的 , 首先要创建引用对象 ; 下面的强引用可以在创建软引用完毕后置空解除引用 , 否则肯定不能被回收 ;

Object softObject = new Object();
SoftReference<Object> softReference1 = new SoftReference<>(softObject);

③ 创建软引用并设置引用队列 : 在上述基础上 , 可以在构造函数中设置一个引用队列参数 ;

Object softObject = new Object();
// 引用队列
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
// 创建软引用, 并将该软引用引用放入引用队列中
SoftReference<Object> softReference2 = new SoftReference<>(softObject, referenceQueue);

④ 上述软引用释放 : 创建的软引用在两种情况下才会释放 :

  • 软引用置空 : GC Root 不可达时回收 ;
  • 内存不足 : 内存不足 , OOM 之前回收 ;

2. 软引用代码示例 :

import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;public class Main {public static void main(String[] args) throws InterruptedException {/*软引用示例1. 创建软引用 : public SoftReference(T referent)2. 创建软引用并放入引用队列中 :public SoftReference(T referent, ReferenceQueue<? super T> q)回收时机 : 软引用在内存不足时才会被回收, OOM 的前一刻*/Object softObject = new Object();// 1. 直接创建软引用SoftReference<Object> softReference1 = new SoftReference<>(softObject);// 2. 创建软引用并放入引用队列中// 引用队列ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();// 创建软引用, 并将该软引用引用放入引用队列中SoftReference<Object> softReference2 = new SoftReference<>(softObject, referenceQueue);// 3. 直接创建软件用SoftReference<Object> softReference3 = new SoftReference<>(new Object());//获取软引用, 调用软引用的 get() 方法 , 即可获取软引用softReference1.get();softReference2.get();// 打印软件用System.out.println("softReference1 : " + softReference1.get());System.out.println("softReference2 : " + softReference2.get());System.out.println("softReference3 : " + softReference3.get());// 软件用被回收之后, 可以通过调用 referenceQueue.poll() 方法, 获取到被回收的引用// 如果获取到 null, 说明该软引用没有被回收// 如果该软件用被回收, 可以获取非空值System.out.println("referenceQueue.poll : " + referenceQueue.poll());// 验证回收机制, 将软引用对象设置为空// 其对应的软引用对象 SoftReference<Object> 回收的时机//  - 1. 置空访问不可达时回收//  - 2. 内存不足 OOM 之前回收softObject = null;// 申请进行垃圾回收, 这里只是申请垃圾回收, 并不会马上调用, 大约几秒内会进行垃圾回收System.gc();Thread.sleep(5_000);// 打印相关变量验证回收机制System.out.println("");System.out.println("softReference1 : " + softReference1.get());System.out.println("softReference2 : " + softReference2.get());System.out.println("softReference3 : " + softReference3.get());// 软件用被回收之后, 可以通过调用 referenceQueue.poll() 方法, 获取到被回收的引用// 如果获取到 null, 说明该软引用没有被回收// 如果该软件用被回收, 可以获取非空值System.out.println("referenceQueue.poll : " + referenceQueue.poll());}}

执行结果 :

softReference1 : java.lang.Object@1b6d3586
softReference2 : java.lang.Object@1b6d3586
softReference3 : java.lang.Object@4554617c
referenceQueue.poll : nullsoftReference1 : java.lang.Object@1b6d3586
softReference2 : java.lang.Object@1b6d3586
softReference3 : java.lang.Object@4554617c
referenceQueue.poll : null

三、 弱引用代码示例


1. 弱引用创建 :

① 直接创建弱引用 : 在软件用构造函数中创建一个软引用 , 不涉及外部引用 ;

WeakReference<Object> weakReference3 = new WeakReference<>(new Object());

② 传入创建好的对象引用创建弱引用 : 弱引用是通过在 弱引用构造函数 传入引用对象创建的 , 首先要创建引用对象 ; 下面的强引用可以在创建软引用完毕后置空解除引用 , 否则肯定不能被回收 ;

Object softObject = new Object();
WeakReference<Object> WeakReference1 = new WeakReference<>(weakObject);

③ 创建弱引用并设置引用队列 : 在上述基础上 , 可以在构造函数中设置一个引用队列参数 ;

Object softObject = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
// 创建弱引用, 并将该弱引用引用放入引用队列中
WeakReference<Object> weakReference2 = new WeakReference<>(weakObject, referenceQueue);

④ 上述软引用释放 : 弱引用不管是否置空 , 只要遇到 GC , 一律回收

2. 软引用代码示例 :

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;public class Main {public static void main(String[] args) throws InterruptedException {/*弱引用示例1. 创建弱引用 : public WeakReference(T referent)2. 创建弱引用并放入引用队列中 :public WeakReference(T referent, ReferenceQueue<? super T> q)回收时机 : 弱引用在 GC 时被回收, 不管内存是否足够*/Object weakObject = new Object();// 1. 直接创建弱引用WeakReference<Object> WeakReference1 = new WeakReference<>(weakObject);// 2. 创建弱引用并放入引用队列中// 引用队列ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();// 创建弱引用, 并将该弱引用引用放入引用队列中WeakReference<Object> weakReference2 = new WeakReference<>(weakObject, referenceQueue);// 3. 直接创建弱引用WeakReference<Object> weakReference3 = new WeakReference<>(new Object());//获取弱引用, 调用弱引用的 get() 方法 , 即可获取弱引用WeakReference1.get();weakReference2.get();// 打印软件用System.out.println("WeakReference1 : " + WeakReference1.get());System.out.println("WeakReference2 : " + weakReference2.get());System.out.println("WeakReference3 : " + weakReference3.get());// 弱引用被回收之后, 可以通过调用 referenceQueue.poll() 方法, 获取到被回收的引用// 如果获取到 null, 说明该弱引用没有被回收// 如果该软件用被回收, 可以获取非空值System.out.println("referenceQueue.poll : " + referenceQueue.poll());// 验证回收机制, 将弱引用对象设置为空// 这里弱引用不管是否置空 , 只要遇到 GC , 一律回收weakObject = null;// 申请进行垃圾回收, 这里只是申请垃圾回收, 并不会马上调用, 大约几秒内会进行垃圾回收System.gc();Thread.sleep(5_000);// 打印相关变量验证回收机制System.out.println("");System.out.println("WeakReference1 : " + WeakReference1.get());System.out.println("WeakReference2 : " + weakReference2.get());System.out.println("WeakReference3 : " + weakReference3.get());// 软件用被回收之后, 可以通过调用 referenceQueue.poll() 方法, 获取到被回收的引用// 如果获取到 null, 说明该弱引用没有被回收// 如果该软件用被回收, 可以获取非空值System.out.println("referenceQueue.poll : " + referenceQueue.poll());}}

执行结果 :

WeakReference1 : java.lang.Object@1b6d3586
WeakReference2 : java.lang.Object@1b6d3586
WeakReference3 : java.lang.Object@4554617c
referenceQueue.poll : nullWeakReference1 : null
WeakReference2 : null
WeakReference3 : null
referenceQueue.poll : java.lang.ref.WeakReference@74a14482

【Android 内存优化】Java 引用类型 ( 强引用 | 软引用 | 弱引用 | 虚引用 )相关推荐

  1. java中四种引用类型(对象的强、软、弱和虚引用)

    2019独角兽企业重金招聘Python工程师标准>>> 对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有 ...

  2. Java:对象的强、软、弱和虚引用

    见:http://zhangjunhd.blog.51cto.com/113473/53092 maven/Java/web/bootstrap/dataTable/app开发QQ群:56686262 ...

  3. 软引用和弱引用的区别_强、软、弱、虚引用的区别和使用

    原文阅读: 强.软.弱.虚引用的区别和使用​mp.weixin.qq.com Java提供了四种级别的应用类型:强引用.软引用.弱引用及虚引用.那么这四种引用类型有什么区别呢? 首先我们通过一张图来看 ...

  4. 对象的强、软、弱和虚引用

    本文介绍对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有 ...

  5. java-基础-强、软、弱、虚引用

    Java的四种引用,强弱软虚,用到的场景. JDK1.2之前只有强引用,其他几种引用都是在JDK1.2之后引入的. 强引用(Strong Reference) 最常用的引用类型,如Object obj ...

  6. jvm系列 (四) ---强、软、弱、虚引用

    java引用 目录 jvm系列(一):jvm内存区域与溢出 jvm系列(二):垃圾收集器与内存分配策略 jvm系列(三):锁的优化 我的博客目录 为什么将引用分为不同的强度 因为我们需要实现这样一种情 ...

  7. JVM 学习(2)—简单理解Java 四大引用(强、软、弱、虚)

    一.Java 引用概述 Java 中出现四种引用是为了更加灵活地管理对象的生命周期,以便在不同场景下灵活地处理对象的回收问题.不同类型的引用在垃圾回收时的处理方式不同,可以用来实现不同的垃圾回收策略. ...

  8. Java对象引用四个级别(强、软、弱、虚)

    转载自 Java对象引用四个级别(强.软.弱.虚) 最近,高级Java技术栈微信群中,有一些猿友在讨论JVM中对象的周期问题,有谈到引用的级别,现在为大家做个总结吧,虽然大多数公司并没有意识或者用到这 ...

  9. 【Java】Java对象引用四个级别(强、软、弱、虚)

    文章目录 1.概述 强引用(StrongReference) 软引用(SoftReference) 弱引用(WeakReference) 虚引用(PhantomReference) 2. 扩展阅读 1 ...

  10. Java的四大引用强、软、弱、虚

    一.什么是引用 首先要明白什么是一个引用呢?Object o = new Object()这就是一个引用了,一个变量指向new出来的对象,这个变量就叫一个引用,引用这个东西,在java里面分4种,普通 ...

最新文章

  1. java读avro的流_0016-Avro序列化反序列化和Spark读取Avro数据
  2. 中文 Python 开源资料合集!这应该是最全的了!
  3. 让你页面速度飞起来 Web前端性能优化
  4. [HTML]HTML5实现可编辑表格
  5. 2021广东高考成绩排名如何查询,2021年广东高考个人排名怎么查询,广东高考成绩排名查询方法...
  6. Connection timed out: connect; Communications link failure
  7. 基于行跟踪的ROWDEPENDENCIES ORA_ROWSCN信息
  8. JUC主要包含哪些功能?
  9. UCI数据集(论文常用数据集)
  10. 愉快地在64位系统下运行汇编
  11. 弹性均质圆环法计算过程_盾构隧道衬砌管片计算方法的比较
  12. 《网易云音乐小程序》开发总结
  13. 最性感的肩膀纹身设计女装 - 5令人惊叹的设计,你会爱!
  14. CAS132172-61-3阳离子脂质体DOTAP科研用
  15. kubectl 命令详解(三十一):rollout history
  16. Python 爬虫下载喜马拉雅音频文件
  17. SRM- Golink体验报告
  18. OpenHarmony在Amlogic A311D芯片平台的快速开发上手指南
  19. requests发送post请求的一些疑点
  20. QtChart柱状图动态加载数据

热门文章

  1. Outlook通过RPC或RPC over HTTPS访问Exchane邮箱:Exchange2003系列之四
  2. MSVCR80D.dll not found 问题(转)
  3. Linux 搭建golang开发环境
  4. over partition by与group by 的区别
  5. 关于js里的document.compatmode
  6. Gradle 修改 Maven 仓库地址(阿里镜像)
  7. IP分类以及特殊IP
  8. JAVA中的常量定义在class中还是interface中比较合理?
  9. Web API-路由(一)
  10. 打造完美的JS树形菜单