zoukankan      html  css  js  c++  java
  • 一,初调HashMap,如何修改JDK的源码进行调试 【深入JDK源码】

    起因:故尝试调试下HashMap实现原理,打印出transient Entry<K,V>[] table  变量的变化情况

    一,在hashmap中加入打印调试信息

    hashmap的实现就是用一个Entry的对象数组Entry中存next形成链,链用于储存key有相同hashcode但key的equas不同的entry,这个网上有很多相关分析;

    那么我现在尝试在hashmap这个类中加入监控信息用来展示它的实现原理

    打开JDK的源码(基于1.6),并在HashMap类中加入新的方法用于打印调试信息,即HashMap中table对象数组变量的变化

     1 public String getTableChageInfor(String messge){
     2         StringBuffer tableInfor=new StringBuffer("========");
     3         tableInfor.append(messge);
     4         tableInfor.append("===start===============");
     5         tableInfor.append("\n");
     6         tableInfor.append("table.length = ");
     7         tableInfor.append(table.length);
     8         tableInfor.append("\n");
     9         tableInfor.append("table node:");
    10         tableInfor.append("\n");
    11         for(Entry enty:table){
    12             tableInfor.append("entry :{");
    13             tableInfor.append(enty);
    14             tableInfor.append("}");
    15             if(enty!=null)//if enty is null,the table didn't add any value in this position
    16             while(enty.next!=null){
    17                 tableInfor.append("-->{");
    18                 tableInfor.append(enty.next);
    19                 tableInfor.append("}");
                       enty=enty.next;
    20             }
    21             tableInfor.append("\n");
    22         }
    23         tableInfor.append("===========end===============");
    24         return tableInfor.toString();
    25     }

    就是迭代打印出table数组对象,和对象的链的所有值,用于监控table值的变化

    二,编译并覆盖rt.jar,实现对JDK代码的修改

    修改hashmap 类后,重新编译HashMap类,JDK编译器 javac HashMap –Xlint:unchecked

    image

    找到生成的hashmap的classes

    image

    把classes copy并替换进 JDK 的JRE\jrt.ar包中

    image

    然后启动eclipse,运行测试,注意你eclipse中配置的JDK要和你修改的一致

    三,简单测试HashMap原理

    1,HashMap的初始化

    image

    很明确. HashMap 初始化的时候就是长度为16的对象数组 (static final int DEFAULT_INITIAL_CAPACITY = 16;)

    2,HashMap的扩容

    根据hashmap中的加载因子定义  static final float DEFAULT_LOAD_FACTOR = 0.75f;

    那么得出,如果有16*0.75即12个,那么table数组将会翻倍扩容,验证下

    image

    可以看到当你put的元素超过了13个时,那么table将会进行扩容,并把原来的值copy进去,其实和ArrayList的实现原理一样,只不过增加了地址定位,链等

    3,HashMap的链

    当key的hashcode相同,equas不同时,就会根据hashcode计算table索引的对应的链添加元素,所以设计了一个equas相同,但是equas不同的key类

     完整代码如下

    View Code
    package org.benson.test;
    
    public class Key {
        private char mapKey;
        @Override
        public int hashCode() {
            return "A".hashCode();
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Key other = (Key) obj;
            if (mapKey != other.mapKey)
                return false;
            return true;
        }
    
        public Key(char mapKey) {
            this.mapKey=mapKey;
        }
    
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return String.valueOf(mapKey);
        }
    }

    添加并打印key

    package org.benson.test;
    
    import java.util.HashMap;
    
    public class Test4MapTable {
    
        /**@author BensonHe QQ 107966750
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            HashMap hmp=new HashMap();
            hmp.put(new Key('A'), "valueA");
            hmp.put(new Key('B'), "valueB");
            System.out.println(hmp.getTableChageInfor("befor"));
        }
    
    }

    run,测试结果如下

    ========befor===start===============
    table.length = 16
    table node:
    entry :{null}
    entry :{null}
    entry :{null}
    entry :{null}
    entry :{null}
    entry :{B=valueB}-->{A=valueA}
    entry :{null}
    entry :{null}
    entry :{null}
    entry :{null}
    entry :{null}
    entry :{null}
    entry :{null}
    entry :{null}
    entry :{null}
    entry :{null}
    ===========end===============
    

    注:

    发现如果根据hashcode计算的index相同,但并非单指hashcode相同,当然hashcode相同计算的index肯定是一样的,具体是在hashmap中实现计算.比如hashcode=18 和 hashcode=33的属于同一个链中

    引用个外部图片表示 

    便生成了对应的链,而不会新占用table的index

     4,原理应用

    要求输出valueA,实现key方法

    import java.util.HashMap;
    
    public class Test4MapTable {
    
    	/**@author BensonHe QQ 107966750
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		HashMap hmp=new HashMap();
    		hmp.put('A', "valueA");
    	    System.out.println(hmp.get(new Key('A')));
    //		System.out.println(hmp.getTableChageInfor("befor"));
    	}
    
    }
    

    其实很简单,覆盖下hashcode和equals方法

    如下

    View Code
    package org.benson.test;
    
    public class Key {
        private char mapKey;
        @Override
        public int hashCode() {
            return String.valueOf(mapKey).hashCode();
        }
    
        @Override
        public boolean equals(Object obj) {
    //        if (this == obj)
    //            return true;
    //        if (obj == null)
    //            return false;
    //        if (getClass() != obj.getClass())
    //            return false;
    //        Key other = (Key) obj;
    //        if (mapKey != other.mapKey)
    //            return false;
            return obj.equals(mapKey);
        }
    
        public Key(char mapKey) {
            this.mapKey=mapKey;
        }
    
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return String.valueOf(mapKey);
        }
    }

    附上 失败尝试

    从JDK源码看到,hashmap的table变量的作用范围是default,即同package可以调用,故尝试继承hashmap 并放在同一个package中

    image

    然后ruan,执行失败

    抛出

    Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.util

    image

    找到java.lang.ClassLoader.preDefineClass,打开源码找到了原因:

    image

    原来所有以java.开头的package都是被禁止使用的,然而hashmap类又是在java.util中,所以此方法不行

    有问题欢迎交流,thanks

  • 相关阅读:
    表格的增删改查
    选择省份时,自动显示对应省份的城市
    弹框提示用户输入
    dom
    css基础
    HTML基础
    B
    poj 1840 Eqs
    hdu 1166 敌兵布阵(线段树)
    poj 2586 Y2K Accounting Bug
  • 原文地址:https://www.cnblogs.com/springsource/p/2832838.html
Copyright © 2011-2022 走看看