Java中四种引用

Java内存管理包括内存分配和内存回收。

  • 内存分配:程序员通过new对象,JVM会自动为该对象分配内存。
  • 内存回收:Java在JVM虚拟机上增加了垃圾回收(Garbage Collection)机制,用以在合适的时间触发垃圾回收,将不需要的内存空间回收释放,避免无限制的内存增长导致的OOM.

其实GC时主要看这个对象是否有引用指向该对象。按照这种引用的强弱的关系, 从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

四种引用

  1. 强引用(StrongReference)

    • 是指创建一个对象并把这个对象赋给一个引用变量。比如Object tv = new Object();

    • 强引用有引用变量指向时永远不会被垃圾回收,JVM宁愿抛出OutOfMemory错误也不会回收这种对象。

    • 如果程序确实不在用到某个强引用变量,通常可以手动将这个引用指向赋值为null。比如常见的集合中claer()方法。下面这段代码就是ArrayListclear()

       /**
        * Removes all of the elements from this list.  The list will
        * be empty after this call returns.
        */
       public void clear() {
           modCount++;
      
           // clear to let GC do its work
           for (int i = 0; i < size; i++)
               elementData[i] = null;
      
           size = 0;
       }
      
  2. 软引用(SoftReference)

    • SoftReference<T> softRef = new SoftReference<>(T t); 这样就可以把一个对象变成软引用
    • 然后通过softRef.get()就能获得这个对象
    • 只有在内存空间不足时,才会被回收的对象;使用的时候记得判空。
    • 可用来实现内存敏感的高速缓存,比如网页缓存、图片缓存等;也能避免内存泄露,但在Android中不建议使用软引用。
  3. 弱引用(WeakReference)

    • WeakReference<T> weakRef = new WeakReference<>(T t); 这样就可以把一个对象变成软引用
    • 然后通过weakRef.get()就能获得这个对象
    • 在 GC 时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存;使用的时候记得判空。
  4. 虚引用(PhantomReferece)

    • 顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。

    • 任何时候都可以被GC回收,引用是最弱的。

    • ReferenceQueue queue = new ReferenceQueue ();
      PhantomReference pr = new PhantomReference (object, queue);

    • 由于引用关系最弱,并且源码中的get方法直接返回null,所以必须配合ReferenceQueue<T>使用

       public T get() {
            return null;
       }
      

Q:Android中为什么不推荐使用软引用(SoftReference)?

Avoid Soft References for Caching
In practice, soft references are inefficient for caching. The runtime doesn't have enough information on which references to clear and which to keep. Most fatally, it doesn't know what to do when given the choice between clearing a soft reference and growing the heap.
在实践中,软引用(soft references)在缓存中是低效的,因为runtime并没有足够的信息来判别应该清除或者保留哪个 SoftReference(持有的对象),更无法判定当 App 要求更多内存的时候,是应该清除 SoftReference,还是增大 App 的Heap。

The lack of information on the value to your application of each reference limits the usefulness of soft references. References that are cleared too early cause unnecessary work; those that are cleared too late waste memory.
你的程序的引用的信息的缺失导致软引用用处的局限性。过早清除的引用会导致无用功,太晚清除又会浪费内存。

Most applications should use an android.util.LruCache instead of soft references. LruCache has an effective eviction policy and lets the user tune how much memory is allotted.
大多数程序应该使用android.util.LruCache来替代软引用,LruCache有着更高效的回收策略,并让用户协调要分配多少内存。

上面这段描述来自官网-Avoid Soft References for Caching

  • 在正常的 JVM中,只要不触发 OOM(达到系统内存上限或者到达 JVM 设定的内存上限),JVM 就应该毫不留情的增大 Heap 来维持应用的正常运行。 而没有必要考虑是先清理SoftReference,还是增大 Heap 。
  • Android Runtime与 JVM 不一样的是:用户 App 通常没有权限来设定自己的最大可用内存,这个是由系统控制的, 单个 App 使用的最大内存容量是固定的 Runtime.getRuntime().maxMemory()

Q:如果一个对象同时有强引用和弱引用与之关联,那GC的时候会回收吗?

伪代码

  T t = new T();
  WeakReference<T> tRef = new WeakReference<>(t);

很显然GC的时候这个t不仅有弱引用还有强引用关联,此时是不会回收的。

Q: 既然虚引用形同虚设,那么它有什么作用?

网上找这样的描述:

  1. Use Cases
    There’re two common use-cases they are used for.
    The first technique is to determine when an object was removed from the memory which helps to schedule memory-sensitive tasks. For example, we can wait for a large object to be removed before loading another one.
    The second practice is to avoid using the finalize method and improve the finalization process.

第一个就是能够知道这个对象回收时机,能在对象被GC时收到系统通知
第二个就是避免使用finalize

参考Phantom References in Java
由于目前没有真正用过虚引用,欢迎补充,多谢~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容

  • 一、引用类型(referenceObject) 概述:java从1.2版本把对象的引用分为四种级别,由高到低分别为...
    Lynn_R01612x2阅读 454评论 1 0
  • 强引用 强引用是使用最普遍的引用:Object o=new Object();特点:不会被GC将对象的引用显示地置...
    Tyhj阅读 959评论 0 0
  • 为了使能更加灵活地控制对象的生命周期。从JDK 1.2版本开始,把对象的引用分为4种级别。这4种级别由高到低依次为...
    Jeffbond阅读 583评论 0 4
  • 1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虚拟机(JVM)垃圾回收器提供...
    简欲明心阅读 89,470评论 17 311
  • 跟一男生上周分了。 对他,是种什么感觉呢?有难过,有痛苦,有恨,有气,有一种憧憬被打碎的感觉,价值观颠覆,不知所措...
    Sussis阅读 135评论 0 0