Java 强/弱/软引用

关于Java的强/软/弱引用,今天总结一下他们的区别和应用。

引用的强弱程度

根据JVM对三种引用的内存回收时机来区分的话,可以把他们按

强引用 > 软引用 > 弱引用

来排列。在JVM运行内存不足时,这三种之中最先被回收的是 弱引用,依次到最后才是强引用(不会被回收)。 但是对于强引用来说,JVM在内存不足时宁可抛出 OOM,也不会随意回收强引用来释放内存。 下面具体说下强引用。

强引用 Strong Reference

在最经常实例化对象的语法里,如果不指定引用类型,那么默认是强引用。

Object  Object = new Object();

分两种情况来说明一下。 · 在方法中的强引用 · 全局强引用

方法中的强引用

在方法内声明一个强引用对象的话,在内存中会分两部分来进行。首先引用会保存在Stack中,而引用的对象Object会存放在堆中。

上面的图说明了JVM的内存模型和各种对象存放的位置。 当方法执行完后,会退出方法栈,此时引用不在,所以Object会被回收。

全局强引用

其实在JVM中没有全局变量这种概念,相对的是全局静态变量。我们可以看一个类Global在编译后的字节码,

public class Global {
    Global global = new Global();

    public Global(){

    }

    public static void main(String[] args) {
      System.out.println("global");
    }
}

javap -c Global.Class

public class Global {
  Global global;

  public Global();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: new           #2                  // class Global
       8: dup
       9: invokespecial #3                  // Method "<init>":()V
      12: putfield      #4                  // Field global:LGlobal;
      15: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #6                  // String global
       5: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

可以看出来,其实非静态的变量也是在默认构造方法中实例化的,但是静态变量就不同了。静态变量是在堆中存放引用和对象, 所以全局静态引用需要在不使用时将它置为null

object = null;

软引用 SoftReference

软引用在JVM内存不足时会被回收,用这种特性,可以在一些内存敏感的场景上用软引用。 比如Bitmap对象,可以用软引用

SoftReference<Bitmap> bitmap = new SoftReference<Bitmap>();

弱引用 WeakReference

弱引用有着比软引用更脆弱的生命周期。即使内存充足,但是只要被GC扫描到就会被回收

WeakReference<String> abcWeakRef = new WeakReference<String>(str);

本文分享自微信公众号 - Android每日一讲(gh_f053f29083b9)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-04-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏marsggbo

c++学习笔记之封装篇(上)

一、类对象 假设我们由Tv这个类,定义如下 注意class结尾要加上分号 class Tv() { int width; int hei...

18860
来自专栏小狼的世界

Python 3.6学习笔记(一)

可以看到,注释以#开头,python的变量不需要任何前缀,行结束不需要结束符号,非常符合我们自然语言的阅读和书写习惯。当语句以:结尾时,缩紧的语句视为代码块。

12220
来自专栏mukekeheart的iOS之旅

final、finally、finalize的区别

final:修饰符,可以用于修饰成员、方法和类。 如果一个类被声明为final,意味着该类不能再派生出新的子类,不能作为父类被继承。因此一个类不能即被声明为ab...

26250
来自专栏about云

spark开发基础之Scala详解apply方法

问题导读 1.什么情况下调用apply方法? 2.apply你认为有哪些作用? 3.方法调用属于apply什么功能? apply网上很多资料,但是总感觉总...

40660
来自专栏CodingToDie

Python学习(四):dict,set和关键字

第4 章 dict,set和关键字 Table of Contents dict set 再谈遍历 标识符(Identifiers) 关键字 判断、循环 函数、...

39540
来自专栏程序员的知识天地

Python正则表达式的7个使用典范

作为一个概念而言,正则表达式对于Python来说并不是独有的。但是,Python中的正则表达式在实际使用过程中还是有一些细小的差别。

13710
来自专栏一“技”之长

JavaScript基础之二——方法与属性 原

    和编译型语言必须由类产生对象不同,JavaScript语言中并没有严格的类的界定,并且对象的属性和方法也可以进行动态的绑定。属性是对象中封装的一些值数据...

7420
来自专栏好好学java的技术栈

“面试不败计划”: java语言基础面试题(二)

10920
来自专栏技术专栏

Scala入门与进阶(四)- Scala面向对象

12320
来自专栏林冠宏的技术文章

由 System.arraycopy 引发的巩固:对象引用 与 对象 的区别

首先明确一点,System.arraycopy 操作的是数组,效果是深复制。 是不是觉得怎么和你印象的中不一样? 重点来了,对于对象数组,例如: User[]...

14840

扫码关注云+社区

领取腾讯云代金券