Java 集合 持有引用 & WeakHashMap

@author ixenos

摘要:强引用、弱引用、WeakHashMap动态回收步骤

Reference引用对象


  • 可获得的(reachable):指在栈中有一个普通的引用正在指向此对象,也可能有更多的中间链接
    • 如果一个对象是可获得的,垃圾回收器(GC)就不能释放它,因为他仍然为程序所用,宁愿耗尽内存也不释放;当一个对象不是可获得的时候,程序无法使用它,此时GC才认为将其回收是安全的

  • Reference对象:如果想继续持有对某个对象的引用,但也希望能够允许GC释放它,就应使用Reference对象作为与普通引用之间的媒介(代理),即普通引用经Reference对象包装过再指向某个对象

  • 普通引用-->Reference对象-->目标对象

Reference引用对象的四种分类(由强到弱)


  • 强引用(Strong Reference):强引用时,就是普通引用,对象是可获得的(reachable)

  • 软引用(Soft Reference):实现内存敏感的高速缓存 //TODO

  • 弱引用(Weak Reference):实现规范映射(canonicalizing mappings),它不妨碍GC回收映射的key或value,规范映射中对象的实例可以在程序的多处被同时使用,以节省存储空间
  • 幻象引用(Phantom Reference):用以调度回收前的清理工作,比Java终止机制灵活

    幻象引用于弱引用和软引用均不同。它控制其指向的对象非常弱(tenuous),以至于它不能获得这个对象。get()方法通常情况下返回的是null值。它唯一的作用就是跟踪列队在ReferenceQuene中的已经死去的对象。
    幻象引用和弱引用的不同在于其入队(enquene)进入ReferenceQuene的方式。当弱引用的对象成为若可到达时,弱引用即列队进入ReferenceQuene。这个入队发生在终结(finialize)和垃圾回收实际发生之前。理论上,通过不正规(unorthodox)的finilize()方法,成为垃圾的对象能重新复活(resurrected),但是弱引用仍然是死的。幻象引用只有当对象在物理上从内存中移出时,才会入队。这就阻止我们重新恢复将死的对象。
    W:终结(Finalization)指比拉圾回收更一般的概念,可以回收对象所占有的任意资源,比如文件描述符和图形上下文等。
    幻象引用由两个好处:
    A:它能确定某一个对象从内存中移除的时间,这也是唯一的方式。通常情况下,这不是非常有用。但是迟早(come in handy)会用到手动处理大图片的情况:如果你确定一张图片需要被垃圾回收,那么在你尝试加载下一张照片前,你应该等待这张照片被回收完成。这样就使得令人恐惧的(dreaded)内存溢出不太可能发生。
    B:虚幻引用能够避终结(finilize)的基本问题。finilize()方法能够通过给一个垃圾对象关联一个强引用使之复活。问题是覆写了finilize()方法的对象在成为垃圾之前,为了回收,垃圾回收期需要执行两次单独的循环。第一轮循环确定某个对象是垃圾,那么它就符合终结finilize的条件。在finilize的过程中,这个对象可能被“复活”。在这个对象被实际移除之前,垃圾回收期不得不重新运行一遍。因为finilization并不是实时调用的,所以在终止进行的过程中,可能发生了gc的多次循环。在实际清理垃圾对象时,这导致了一些延时滞后。这将导致Heap中有大量的垃圾导致内存溢出。
    幻象引用不可能发生以上的情况,当幻象引用入队时,它实际上已经被移除了内存。幻象内存无法“复活”对象。这发现这个对象时虚幻可到达时,在第一轮循环中,它就被回收。
    可以证明,finilize()方法从不在第一种情况下使用,但是虚幻引用提供了一种更安全和有效的使用和被排除掉的finilize方法的机制,使得垃圾回收更加简单。但是因为有太多的东西需要实现,我通常不适用finilize。

    幻象引用原理

ReferenceQueue引用队列


  • 使用软引用弱引用时们可以选择是否要将他们放入ReferenceQueue(用作“回收前清理工作”的工具),而幻象引用回收后进入ReferenceQueue

  • 幻象引用弱引用的不同在于其入队(enquene)进入ReferenceQuene的方式:

    • 当弱引用的对象成为若可到达时,弱引用即列队进入ReferenceQuene。这个入队发生在终结(finialize)和垃圾回收实际发生之前。理论上,通过不正规(unorthodox)的finilize()方法,成为垃圾的对象能重新复活(resurrected),但是弱引用仍然是死的,因为没有引用指向它;

    • 而幻象引用只有当对象在物理上从内存中移出时,才会入队。这就阻止我们重新恢复将死的对象;

    • 终结(Finalization)指比拉圾回收更一般的概念,可以回收对象所占有的任意资源,比如文件描述符和图形上下文等

  • 弱引用为例

    • 一旦弱引用返回null值,那么其指向的对象就变成了垃圾,这个弱引用对象也就没有用了。这通常意味着要进行一定方式的清理(cleanup)。例如,WeakHashmap将会移除一些死的(dread)的entry,避免持有过多死的弱引用。ReferenceQuene能够轻易的追踪这些死掉的弱引用;

    • 可以将ReferenceQuene传入WeakHashmap的构造方法(constructor)中,这样,一旦这个弱引用指向的对象成为垃圾,这个弱引用将加入ReferenceQuene中

WeakHashMap弱散列映射表


  • WeakHashMap使用弱引用(WeakReference)保存键,称为弱键

  • ref-->weak ref-->key ,  if (ref==null) , than ( weak ref-->ref queue , WeakHashMap将删除对应的条目)

  • 动态回收的步骤:

(1) 新建WeakHashMap,将“键值对”添加到WeakHashMap中

将“键值对”添加到WeakHashMap中时,添加的键都是弱键;实际上,WeakHashMap是通过数组table保存Entry(键值对);每一个Entry实际上是一个单向链表,即Entry是键值对链表;

(2) 当某“弱键”不再被其它对象引用,并被GC回收时。在GC回收该“弱键”时,这个“弱键”也同时会被添加到queue队列中

例如,当我们在将“弱键”key添加到WeakHashMap之后;后来将key设为null。这时,便没有外部外部对象再引用该了key;接着,当Java虚拟机的GC回收内存时,会回收key的相关内存;同时,将key添加到queue队列中;

(3) 当下一次我们需要操作WeakHashMap时,会先同步table和queue。table中保存了全部的键值对,而queue中保存被GC回收的“弱键”;同步它们,就是删除table中被GC回收的“弱键”对应的键值对

例如,当我们“读取WeakHashMap中的元素或获取WeakReference的大小时”,它会先同步table和queue,目的是“删除table中被GC回收的‘弱键’对应的键值对”。删除的方法就是逐个比较“table中元素的‘键’和queue中的‘键’”,若它们相当,则删除“table中的该键值对”。

-

Java 集合 持有引用 & WeakHashMap的更多相关文章

  1. Java 集合系列 13 WeakHashMap

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  2. Java 集合系列 09 HashMap详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  3. Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  4. Java 集合系列 17 TreeSet

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  5. Java 集合系列 16 HashSet

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  6. Java 集合系列 15 Map总结

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  7. Java 集合系列 14 hashCode

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  8. Java 集合系列 12 TreeMap

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  9. Java 集合系列 11 hashmap 和 hashtable 的区别

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

随机推荐

  1. [SQL基础教程] 4-4 事务

    [SQL基础教程] 4 数据更新 4-4 事务 事务 需要在同一处理单元中执行的一系列更新处理的集合 创建事务 事务开始语句; DML语句1; DML语句2; . . . 事务结束语句; 事务开始语句 ...

  2. jq屏蔽f5

    //屏蔽F5 $(document).ready(function () { $(document).bind("keydown", function (e) { e = wind ...

  3. JAVA上连接ubuntu14.04上的Hbase

    对于新手来说,连接虚拟机上的Hbase有点繁琐,而且网上的配置不太适合初学者,今天我就整理了一下,希望对你们有帮助,第一次发博客. 1.首先去官网下载Hbase的压缩包.我这里用的是1.2.1 htt ...

  4. nginx https 配置

    1.创建证书并下载(下载完成后有两个文件) *.pem *.key 2.将两个文件放在linux 某个目录下 3.配置nginx的conf配置文件 server{ # https 端口默认不是80,是 ...

  5. AxonVR:体验有触觉有温度的VR世界

    提到VR,通常指的是 Oculus Rift 及 HTC Vive的头盔:它们以视觉及听觉使你感到身处虚拟世界.头盔成功的在视觉及听觉感官上蒙骗了你,但我们体验现实的感官不仅于此.绝大多数的VR产品忽 ...

  6. 利用python3.5 构建流媒体后台音视频切换的服务端程序

    #!/usr/bin/env python3.5.0 # -*- coding:utf8 -*- import os,sys,socket,hashlib,time,select,threading, ...

  7. JavaScript实现360度全景图片展示效果

    全景拍摄:所谓“全景拍摄”就是将所有拍摄的多张图片拼成一张全景图片.它的基本拍摄原理是搜索两张图片的边缘部分,并将成像效果最为接近的区域加以重合,以完成图片的自动拼接.现在的智能手机也基本带这个功能. ...

  8. 在CentOS上安装第三方软件库EPEL

    Extra Packages for Enterprise Linux (EPEL)[企业版 Linux 附加软件包(以下简称 EPEL)]是一个由特别兴趣小组创建.维护并管理的,针对 红帽企业版 L ...

  9. python numpy基础 数组和矢量计算

    在python 中有时候我们用数组操作数据可以极大的提升数据的处理效率, 类似于R的向量化操作,是的数据的操作趋于简单化,在python 中是使用numpy模块可以进行数组和矢量计算. 下面来看下简单 ...

  10. 各种编码之间的关系以及getBytes的使用

    编码基础知识参考http://my.oschina.net/chape/blog/201725 我对此作了简单的概括 iso8859-1 (通常叫做Latin-1) 属于单字节编码,最多能表示的字符范 ...