`

引用类,WeakHashMap,以及让value自动回收

阅读更多
   如果要彻底明白WeakHashMap这个类,需要联系GC和对象的可触及状态(强可触及、软可触及……)来看,可参考JVM规范里相关内容。
关于gc和对象可触及性这两块,这里我就不展开了。不过,如果要看懂本文,最好还是先去看下这两块的机制。
  本文分三块:
  1、jdk引用类介绍(如WeakReference)
  2、WeakHashMap工作机制介绍
  3、自己实现一个类,让它可以自动回收value的堆区(自认为这是本文亮点

PS:本文有误,value的堆区也会自动回收,因为在调用put方法的时候,内部调用了getTable方法,而getTable方法内部又调用了expungeStaleEntries方法,在expungeStaleEntries方法内部处理了已经由gc的后台线程Reference Handler加入到ReferenceQueue<K>中的Reference对象,该对象的内部的value被指向null,从而提示gc未来可回收value原对象的堆区空间了。
故本文第三条完全没有必要,WeakHashMap本身已经能很好的回收value的堆区了,当初不知为何有那样的测试结果出来,抱歉了!各位


1、jdk引用类介绍

而jdk里的引用类体系为:

以软引用为例,看下引用的内存结构:


而,对应各种可触及性有很多引用类型
   1、强可触及性
   2、软可触及性----SoftReference
   3、弱可触及性--WeakReference
   4、可复活性---FinalReference
   5、影子可触及性(译法可不同)---PhantomReference
   6、不可触及性
引用类的学习,如果需要详细资料,请参考:
弱引用:http://www.ibm.com/developerworks/cn/java/j-jtp11225/
软引用:http://www.ibm.com/developerworks/cn/java/j-jtp01246.html
引用类使用指南:https://www.ibm.com/developerworks/cn/java/j-refs/
《深入Java虚拟机》
尤其前三篇IBM开发社区的文章,分析的相当到位!!!
好了,下面正式开始谈WeakHashMap



2、WeakHashMap工作机制介绍:
      这里用简单的话写出,可能不能完全描述清晰,尤其对初学者而言。先这样写着,如果需要,我会专门写一篇WeakHashMap源码分析文章,然后附上链接,那就看大家需不需要了。
      在put一个新pair的时候,实际上是将key的引用封装成了一个 WeakReference<K>对象(这不同于HashMap中的直接使用key作为Entry的属性)。于是在每次调用WeakHashMap的
        
 gettable()
          size()
          resize()


方法的时候都会调用expungStaleEntries()方法来清除处理已经被gc加入到队列中的弱引用。处理方法见expungStaleEntries方法体:

private void expungeStaleEntries() {
	Entry<K,V> e;
        while ( (e = (Entry<K,V>) queue.poll()) != null) {
            int h = e.hash;
            int i = indexFor(h, table.length);

            Entry<K,V> prev = table[i];
            Entry<K,V> p = prev;
            while (p != null) {
                Entry<K,V> next = p.next;
                if (p == e) {
                    if (prev == e)
                        table[i] = next;
                    else
                        prev.next = next;
                    e.next = null;  // Help GC
                    e.value = null; //  "   "
                    size--;
                    break;
                }
                prev = p;
                p = next;
            }
        }
}

上面这段代码实际上做的工作是:将已经被加入队列中的弱引用对应的Entry的从整个map的结构中移除,然后断开Entry指向 value的引用,加速gc回收value的堆区空间。而key指向的堆区对象已经在这个引用对象本身被GC加入到queue之前已经被释放了所有所有的弱引用,进入可复活状态或者已经经过可复活状态等待被回收了。


3、自己实现一个类,让它可以自动回收value的堆区
不过,WeakHashMap的设计有一个地方让我们不爽,如果我们没有调用size()方法,value在堆区的空间就不会被释放。于是我写了一个类MyWeakHashMap来替代WeakHashMap:
如果要获得完整代码,请下载附件。
/**
 * 自己实现的类,替代jdk中的类java.util.WeakHashMap。
 * 和WeakHashMap比较,无需调用该java.util.WeakHashMap
 * 中的size()等方法,该类可以自动释放内部类Entry中的
 * value的堆空间。
 * @author 贾懂凯 
 * 
 * @param <K>
 * @param <V>
 */
public class MyWeakHashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>{
	 //如果有兴趣,请下载运行
}


附件中同时有一个测试类Test,通过测试,能很明确地看出我设计的类和jdk自带的WeakHashMap类的区别。
下面给出测试代码和结果:
如果是jdk自带类WeakHashMap:
import java.util.ArrayList;
import java.util.WeakHashMap;
import java.util.List;
public class Test {
	public static void main(String args[]){
		
		//测试1
		
		 List<WeakHashMap<byte[][], byte[][]>> maps = new ArrayList<WeakHashMap<byte[][], byte[][]>>(); 
		 for (int i = 0; i < 1000; i++) {  
		        WeakHashMap<byte[][], byte[][]> d = new WeakHashMap<byte[][], byte[][]>();  
		        d.put(new byte[1000][1000], new byte[1000][1000]);  
		        maps.add(d);  
		        System.gc();  
		        System.err.println(i);  
		    } 
	}
}

结果
写道
0
1
……
63

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at Test.main(
Test.java:18)

我们发先报出了OOM(内存溢出)异常。使用我定义的类,就不会出现OOM:


import java.util.WeakHashMap;
import java.util.List;
public class Test {
	public static void main(String args[]){
		//测试2
		 List<MyWeakHashMap<byte[][], byte[][]>> maps = new ArrayList<MyWeakHashMap<byte[][], byte[][]>>();  
		 for (int i = 0; i < 1000; i++) {  
		        MyWeakHashMap<byte[][], byte[][]> d = new MyWeakHashMap<byte[][], byte[][]>();  
		        d.put(new byte[1000][1000], new byte[1000][1000]);  
		        maps.add(d);  
		        System.gc();  
		        System.err.println(i);  
		    } 
	}
}

结果:
写道
0
1
2
3
……

不会出现OOM(内存溢出)异常。






  • 大小: 38.2 KB
  • 大小: 13.1 KB
分享到:
评论

相关推荐

    Java弱引用与WeakHashMap

    在《Effective Java 2nd Edition》中,第6条“消除过期的对象引用”提到,虽然Java有垃圾回收机制,但是只要是自己管理的内存,应该警惕内存泄露的问题,例如的对象池、缓存中的过期对象都有可能引发内存泄露的问题...

    java集合-WeakHashMap的使用

    WeakHashMap是Java中的一种特殊的哈希表实现,它使用弱引用(Weak Reference)来保存键对象。当键对象没有被其他强引用引用时,在垃圾回收时会自动从WeakHashMap中移除对应的键值对。

    Java期末复习-类集框架

    SortedMap接口、HashMap类、Hashtable类、Properties类、Map.Entry接口、WeakHashMap类、IndentityHashMap类 集合输出: Iterator、ListIterator、foreach、废除的Enumeration Collections工具类 Comparable接口、...

    WeakHashMap的使用方法详解

    主要介绍了WeakHashMap的使用方法详解的相关资料,希望通过本文能帮助到大家,让大家理解掌握这部分内容,需要的朋友可以参考下

    解析WeakHashMap与HashMap的区别详解

    本篇文章是对WeakHashMap与HashMap的区别进行了详细的分析介绍,需要的朋友参考下

    Java 基础核心总结 +经典算法大全.rar

    Hashtable 类IdentityHashMap 类WeakHashMap 类 Collections 类集合实现类特征图 泛形 泛型的使用 用泛型表示类 用泛型表示接口泛型方法 泛型通配符 反射 Class 类Field 类Method 类ClassLoader 类 枚举 枚举特性 ...

    Java编程WeakHashMap实例解析

    主要介绍了Java编程WeakHashMap实例解析,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下

    疯狂JAVA讲义

    7.6.3 WeakHashMap实现类 279 7.6.4 IdentityHashMap实现类 280 7.6.5 EnumMap实现类 281 7.7 HashSet和HashMap的性能选项 282 7.8 操作集合的工具类:Collections 283 7.8.1 排序操作 283 7.8.2 查找,替换...

    java集合框架 解析

    java集合框架 3.6. LinkedHashSet类 4. Map接口 4.1. Map.Entry接口 4.2. SortedMap接口 4.3. AbstractMap抽象类 4.4. HashMap类和TreeMap类 4.4.1. HashMap类 ...4.6. WeakHashMap类 4.6. IdentityHashMap类

    Java优化编程(第2版)

    1.11.2 引用类中的静态变量与方法的 …… 小结 第4章 java核心类与性能优化 4.1 散列表类与性能优化 4.1.1 线程同步散列表类 4.1.2 设置arraylist初始化容量 4.1.3 arraylist与linkedlist 4.2 string类与性能优化 ...

    线程死锁CPU过高,请求原因分析

    线程死锁 CPU过高 WeakHashMap 请求原因分析

    Java集合类操作优化经验总结

    本文首先针对 Java 集合接口进行了一些介绍,并对这些接口的实现类进行详细描述,包括 LinkedList、ArrayList、Vector、Stack、Hashtable、HashMap、WeakHashMap 等,然后对一些实现类的实现方式和使用经验进行讲解...

    清华妹子的Java仓库(进阶学习路线)

    本仓库记录了我的Java学习进阶之路,涵盖了Java基础、JDK源码、JVM中的重要知识,附有代码和博客讲解,旨在提供一个Java在线共享学习平台,帮助更多的...Java集合框架源码解读(4)——WeakHashMap Java集合框架源码解读

    WeakObjectPool:用于在对象生命周期中将对象附加到对象(即装饰器)的池

    #弱对象池问题您是否曾经想跟踪一堆对象而不直接引用它们,以免使用弱引用干扰它们的自然生命周期? 您是否曾经尝试过在运行时扩展Java对象?解决方案WeakObjectPool :用于保存和扩展[弱引用的对象]的池( “ ...

    超全Java集合框架讲解.md

    - WeakHashMap - Hashtable - Collection 集合体系详解 - Set 接口 - AbstractSet 抽象类 - SortedSet 接口 - HashSet - LinkedHashSet - TreeSet - List 接口 - AbstractList 和 AbstractSequentialList...

    picketlink-jbas-common-2.6.0.CR4.zip

    Java-WeakIdentityHashMap.zip,weakhashmap identityhashmapa独立库的组合,用于weakidantityhashmap实现内/外字段

    各种集合的总结

    总结了集合中常用的一点点,希望可以共享 List:LinkedList,ArrayList,Vector(Stack),Set Map:Hashtable,HashMap,WeakHashMap

    javabitset源码-JerrySoundCode:杰瑞声码

    WeakHashMap (done) 并发集合 ArrayBlockingQueue(done) LinkedBlockingDeque (done) LinkedBlockingQueue (done) PriorityBlockingQueue (done) ConcurrentHashMap (done) ConcurrentLinkedQueue (done) C

    javalruleetcode-dsal:数据结构与算法个人整理

    java lru leetcode 基础算法 快速排序: 随机枢纽元快排、三路快排、三数中值快排 归并排序: 自顶向下归并、自底向上...WeakHashMap Leetcode 刷题记录 栈实现队列、队列实现栈、猫狗队列、带有最小值的栈、LRU、数据

    Thinking in Java 4th Edition

    What’s Inside Preface 1 Java SE5 and SE6 .................. 2 Java SE6 ............................................The 4th edition...........................Changes ...........................................

Global site tag (gtag.js) - Google Analytics