转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52637333

背景:收到公众投稿,《从面试题中看Java的Reference(引用)》,分析的很不错,总感觉少了实际的例子和应用场景。于是结合自己工作中场景,小总结一下。看下Agenda如下:

  • 强引用
  • 软引用
  • 弱引用
  • 什么时候使用软引用,什么时候使用弱引用?
  • 虚引用

一、强引用

Java中的引用,类似于C++的指针。通过引用,可以对堆中的对象进行操作。在某个函数中,当创建了一个对象,该对象被分配在堆中,通过这个对象的引用才能对这个对象进行操作。

假设以上代码是在方法内运行的,那么局部变量str将被分配在栈空间上,而对象StringBuffer实例,被分配在堆空间中。局部变量str指向StringBuffer实例所在的堆空间,通过str可以操作该实例,那么str就是StringBuffer的引用。

此时,运行一个赋值语句:

那么,str所指向的对象也将被str1所指向,同时在局部栈空间上会分配空间存放str1变量。此时,该StringBuffer实例就有两个引用。对引用的”==”操作用于表示两个操作数所指向的堆空间地址是否相同,不表示两个操作数所指向的对象是否相等。

强引用特点:

  • 强引用可以直接访问目标对象。
  • 强引用所指向的对象在任何时候都不会被系统回收。JVM宁愿抛出OOM异常,也不会回收强引用所指向的对象。
  • 强引用可能导致内存泄露。

二、软引用

软引用是除了强引用外,最强的引用类型。可以通过java.lang.ref.SoftReference使用软引用。一个持有软引用的对象,不会被JVM很快回收,JVM会根据当前堆的使用情况来判断何时回收。当堆的使用率临近阈值时,才会回收软引用的对象。

看下我工作中使用到软引用的场景,加载一个1080x1920分辨率的图,约900多K, 对于我们来说,这个图已是非常大了。

  • 首先通过BitmapFactory.decodeStream构造一个大图bitmap
  • 然后把这个bitmap转成Drawble类型,构成强引用。
  • 接着使用SoftReference构造这个drawable对象的软引用drawables.
  • 最后通过软引用的get()方法,取得drawable对象实例的强引用,发现对象被未回收。在GC在内存充足的情况下,不会回收软引用对象。

  • 在实际中,一起请求很多相关图片,从网络,这时就会请求非常多的内存空间,导致内存吃紧,系统开始会GC。这次GC后,drawables.get()不再返回Drawable对象,而是返回null,这时屏幕上背景图不显示,说明在系统内存紧张的情况下,软引用被回收。

  • 使用软引用以后,在OutOfMemory异常发生之前,这些缓存的图片资源的内存空间可以被释放掉的,从而避免内存达到上限,避免Crash发生。

  • 需要注意的是,在垃圾回收器对这个Java对象回收前,SoftReference类所提供的get方法会返回Java对象的强引用,一旦垃圾线程回收该Java对象之后,get方法将返回null。所以在获取软引用对象的代码中,一定要判断是否为null,以免出现NullPointerException异常导致应用崩溃。

到底什么时候使用软引用,什么时候使用弱引用呢?

个人认为,如果只是想避免OutOfMemory异常的发生,则可以使用软引用。如果对于应用的性能更在意,想尽快回收一些占用内存比较大的对象,则可以使用弱引用。

还有就是可以根据对象是否经常使用来判断。如果该对象可能会经常使用的,就尽量用软引用。如果该对象不被使用的可能性更大些,就可以用弱引用。

另外,和弱引用功能类似的是WeakHashMap。WeakHashMap对于一个给定的key,其映射的存在并不阻止垃圾回收器对该键的回收,回收以后,其条目从映射中有效地移除。WeakHashMap使用ReferenceQueue实现的这种机制。

三、 弱引用

弱引用是一种比软引用较弱的引用类型。在系统GC时,只要发现弱引用,不管系统堆空间是否足够,都会将对象进行回收。但是,由于垃圾回收器的线程通常优先级很低,因此,并一不定能很快的发现持有弱引用的对象。这种情况下,弱引用对象可以存在较长的一段时间。一旦一个弱引用对象被垃圾回收器回收,便会加入到一个注册引用队列中。

看一个工作中实例:播放器的播放Panel,是一个View,就是在视频播放时,可以show、hide, 也可以拖拽进度条之类,还有上面的音量,亮度调节等。这样一个view,我们用弱引用,因为在视频播放过程中,不论硬解还是软解,都将占用大量内存。保证视频的渲染效果。

在VideoControllerView.java 有如下一段代码:

在GC之前,弱引用对象并未被垃圾回收器发现,因此通过mView.get()方法可以取得对应的强引用。但是只要进行垃圾回收,弱引用对象一旦被发现,便会立即被回收,并加入注册引用队列中。此时,再次通过mView.get()方法取得强引用就会失败。

注意:软引用,弱引用都非常适合来保存那些可有可无的缓存数据。如果这样做,当系统内存不足时,这些缓存数据会被回收,不会导致内存溢出。而当内存资源充足时,这些缓存数据又可以存在相当长的时间。

四、 虚引用

  • 虚引用是所有引用类型中最弱的一个。一个持有虚引用的对象,和没有引用几乎是一样的,随时都可能被垃圾回收器回收。当试图通过虚引用的get()方法取得强引用时,总是会失败。并且,虚引用必须和引用队列一起使用,它的作用在于跟踪垃圾回收过程。
  • 当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在垃圾回收后,销毁这个对象,奖这个虚引用加入引用队列。
  • 实际中几乎没用,暂不介绍。

最后一张图总结下:

第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。

如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易

Android性能提升之强引用、软引用、弱引用、虚引用使用的更多相关文章

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

    转自: http://zhangjunhd.blog.51cto.com/113473/53092 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无 ...

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

    1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK ...

  3. Java对象的强、软、弱和虚引用详解

    1.对象的强.软.弱和虚引用 转自:http://zhangjunhd.blog.51cto.com/113473/53092/ 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无 ...

  4. java基础知识再学习--集合框架-对象的强、软、弱和虚引用

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://zhangjunhd.blog.51cto.com/113473/53092 本文 ...

  5. Java对象的强、软、弱和虚引用原理+结合ReferenceQueue对象构造Java对象的高速缓存器

    //转 http://blog.csdn.net/lyfi01/article/details/6415726 1.Java对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变 ...

  6. Java:对象的强、软、弱和虚引用[转]

    原文链接:http://zhangjunhd.blog.51cto.com/113473/53092/ 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法 ...

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

    对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2 ...

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

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

  9. 0030 Java学习笔记-面向对象-垃圾回收、(强、软、弱、虚)引用

    垃圾回收特点 垃圾:程序运行过程中,会为对象.数组等分配内存,运行过程中或结束后,这些对象可能就没用了,没有变量再指向它们,这时候,它们就成了垃圾,等着垃圾回收程序的回收再利用 Java的垃圾回收机制 ...

  10. Java中四种引用:强、软、弱、虚引用

    这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...

随机推荐

  1. python-文件操作和集合

    1.打开文件 如果文件不存在会报错 f = open('information.txt','r+') 2.读取文件 read 读取文件 readline 读取文件的一行内容 readlines 读取文 ...

  2. Linux下 Apache Vhost 配置 防止403

    首先,贴一份正确的配置(最简单的) <VirtualHost *:80> DocumentRoot /home/ubuntu/www/spider/public ServerName sp ...

  3. [USACO13OPEN]重力异常

    题目描述 船长正在拯救她的船员,Beefalo 博士. 和所有伟大的冒险故事一样,这个故事也是发生在一个2D平面上的.囧 这个平面是M*N的格子组成的网格,代表着船长的世界的一个侧视图. 有些格子是空 ...

  4. [Codeforces]856D - Masha and Cactus

    题目大意:给出一棵树和若干条可以加入的边,要求加入若干条边使图是仙人掌并且加入的边权和最大,仙人掌定义为没有一个点属于超过1个环.(n,m<=200,000) 做法:这题的仙人掌跟平时见到的不太 ...

  5. ●POJ 2007 Scrambled Polygon

    题链: http://poj.org/problem?id=2007 题解: 计算几何,极角排序 按样例来说,应该就是要把凸包上的i点按 第三像限-第四像限-第一像限-第二像限 的顺序输出. 按 叉积 ...

  6. NOIP 2013

    Prob.1 转圈游戏 找到循环节,然后快速幂.代码: #include<cstdio> #include<cstring> #include<iostream> ...

  7. centos下 apache+mysql+php的安装

    一.安装 MySQL 首先来进行 MySQL 的安装.打开超级终端,输入: [root@localhost ~]# yum install mysql mysql-server 安装完毕,让 MySQ ...

  8. salesforce lightning零基础学习(二) lightning 知识简单介绍----lightning事件驱动模型

    看此篇博客前或者后,看一下trailhead可以加深印象以及理解的更好:https://trailhead.salesforce.com/modules/lex_dev_lc_basics 做过cla ...

  9. 利用maven打jar包(项目来自GitHub)

    1.首先去GitHub上clone一个项目.(前提,maven项目) 2.切换到项目根目录. 3.执行mvn package. 第一次操作失败: 分析错误原因(javac):maven无法找到jdk, ...

  10. spring boot+mybaits+mysql+generato(逆向工程)+前后台数据交互

    如按照我博客上没有弄出来 请在下面留言 我好修改 谢谢 小弟使用的是Eclipse 首先下载STS插件 help--->Elipse Marketplace--->find搜索栏里面搜索S ...