RSS
热门关键字:  java  Ajax  JSP  JSF  Struts
当前位置 : 首页>Java>列表

全面解析Java中的类和对象的初始化过程

来源: 作者: 时间:2007-10-24 点击:

 //Field SINGLE_ENUM_RESOLVER:Lcom/ccb/framework/enums/CachingEnumResolver;
 10: new #18;
 //class HashMap ②
 13: dup
 14: invokespecial #19;
 //Method java/util/HashMap."":()V
 17: putstatic #21;
 //Field CODE_MAP_CACHE:Ljava/util/Map;
 20: getstatic #21;
 //Field CODE_MAP_CACHE:Ljava/util/Map;
 23: ldc #23;
 //String 0
 25: ldc #25;
 //String 北京市
 27: invokeinterface #31, 3;
 //InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; ③
 32: pop 33: returnprivate com.ccb.framework.enums.CachingEnumResolver();
 Code: 0: aload_0 1: invokespecial #34;
 //Method java/lang/Object."":()V 4: invokestatic #37;
 //Method initEnums:()V ④ 7: returnpublic static void initEnums();
 Code: 0: getstatic #21;
 //Field CODE_MAP_CACHE:Ljava/util/Map;
 ⑤ 3: ifnonnull 24 6: getstatic #44;
 //Field java/lang/System.out:Ljava/io/PrintStream;
 9: ldc #46;
 //String CODE_MAP_CACHE为空,问题在这里开始暴露.
 11: invokevirtual #52;
 //Method java/io/PrintStream.println:(Ljava/lang/String;)V 14: new #18;
 //class HashMap 17: dup 18: invokespecial #19;
 //Method java/util/HashMap."":()V ⑥ 21: putstatic #21;
 //Field CODE_MAP_CACHE:Ljava/util/Map;
 24: getstatic #21;
 //Field CODE_MAP_CACHE:Ljava/util/Map;
 27: ldc #54;
 //String 1 29: ldc #25;
 //String 北京市 31: invokeinterface #31, 3;
 //InterfaceMethod java/util/Map.put:(Ljava/lang/Object;
 Ljava/lang/Object;)Ljava/lang/Object;
 ⑦ 36: pop 37: getstatic #21;
 //Field CODE_MAP_CACHE:Ljava/util/Map;
 40: ldc #56;
 //String 2 42: ldc #58;
 //String 云南省 44: invokeinterface #31, 3;
 //InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 ⑧ 49: pop 50: returnpublic java.util.Map getCache();
 Code: 0: getstatic #21;
 //Field CODE_MAP_CACHE:Ljava/util/Map;
 3: invokestatic #66;
 //Method java/util/Collections.unmodifiableMap:(Ljava/util/Map;)Ljava/util/Map;
 6: areturnpublic static com.ccb.framework.enums.CachingEnumResolver getInstance();
 Code: 0: getstatic #16;
 //Field SINGLE_ENUM_RESOLVER:Lcom/ccb/framework/enums/CachingEnumResolver;
 ⑨ 3: areturn}

  如果上面[清单一]显示,清单内容是在 JDK1.4 环境下的字节码内容,可能这份清单对于很大部分兄弟来说确实没有多少吸引力,因为这些 JVM 指令确实不像源代码那样漂亮易懂。但它的的确确是查找和定位问题最直接的办法,我们想要的答案就在这份 JVM 指令清单里。

  现在,让我们对该类从类初始化到对象实例初始化全过程分析[清单一]中的代码执行轨迹。

  如前面所述,类初始化是在类真正可用时的最后一项前阶工作,该阶段负责对所有类正确的初始化值,此项工作是线程安全的,JVM会保证多线程同步。

  第1步:调用类初始化方法 CachingEnumResolver.(),该方法对外界是不可见的,换句话说是 JVM 内部专用方法,() 内包括了 CachingEnumResolver 内所有的具有指定初始值的类变量的初始化语句。要注意的是并非每个类都具有该方法,具体的内容在前面已有叙述。

  第2步:进入 () 方法内,让我们看字节码中的 "①" 行,该行与其上面两行组合起来代表 new 一个 CachingEnumResolver 对象实例,而该代码行本身是指调用 CachingEnumResolver 类的 ()方法。每一个 Java 类都具有一个 () 方法,该方法是 Java 编译器在编译时生成的,对外界不可见,() 方法内包括了所有具有指定初始化值的实例变量初始化语句和java类的构造方法内的所有语句。对象在实例化时,均通过该方法进行初始化。然而到此步,一个潜在的问题已经在此埋伏好,就等着你来犯了。

  第3步:让我们顺着执行顺序向下看,"④" 行,该行所在方法就是该类的构造器,该方法先调用父类的构造器 () 对父对象进行初始化,然后调用 CachingEnumResolver.initEnum() 方法加载数据。

  第4步:"⑤" 行,该行获取 "CODE_MAP_CACHE" 字段值,其运行时该字段值为 null。注意,问题已经开始显现了。(作为程序员的你一定是希望该字段已经被初始化过了,而事实上它还没有被初始化)。通过判断,由于该字段为 NULL,因此程序将继续执行到 "⑥" 行,将该字段实例化为 HashMap()。

最新评论共有 0 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册
Google Adsense
相关文章