频 道 直 达 - 新闻 - 读书 - 培训 - 教程 - 前沿 - 组网 - 系统应用 - 安全 - 编程 - 存储 - 操作系统 - 数据库 - 服务器 - 专题 - 产品 - 案例库 - 技术圈 - 博客 - BBS
51CTO.COM_中国领先的IT技术网站
找资料:

解析Java类和对象的初始化过程(4)

作者: 出处:天新网  (  ) 砖  (  ) 好  评论 ( ) 条  进入论坛
更新时间:2006-10-09 10:38
关 键 词:Java    对象  初始化
阅读提示:本文主要对类和对象初始化全过程进行分析,通过一个实际问题引入,将源代码转换成JVM字节码后,对JVM执行过程的关键点进行全面解析,并在文中穿插入了相关JVM规范和JVM的部分内部理论知识,以理论与实际结合的方式介绍对象初始化和类初始化之间的协作以及可能存在的冲突问题。

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

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

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

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

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

第5步:在“⑦”、“⑧”行,其功能就是为“CODE_MAP_CACHE”字段填入两条数据。

第6步:退出对象初始化方法<init>(),将生成的对象实例初始化给类字段“SINGLE_ENUM_RESOLVER”。(注意,此刻该对象实例内的类变量还未初始化完全,刚才由<init>()调用initEnum()方法赋值的类变量“CODE_MAP_CACHE”是<clinit>()方法还未初始化字段,它还将在后面的类初始化过程再次被覆盖)。

第7步:继续执行<clinit>()方法内的后继代码,“②”行,该行对“CODE_MAP_CACHE”字段实例化为HashMap实例(注意:在对象实例化时已经对该字段赋值过了,现在又重新赋值为另一个实例,此刻“CODE_MAP_CACHE”变量所引用的实例的类变量值被覆盖,到此我们的疑问已经有了答案)。

第8步:类初始化完毕,同时该单态类的实例化工作也完成。

通过对上面的字节码执行过程分析,或许你已经清楚了解到导致错误的深层原因了,也或许你可能早已被上面的分析过程给弄得晕头转向了,不过也没折,虽然我也可以从源代码的角度来阐述问题,但这样不够深度,同时也会有仅为个人观点、不足可信之嫌。

如何解决

要解决上面代码所存在的问题很简单,那就是将“SINGLE_ENUM_RESOLVER”变量的初始化赋值语句转移到getInstance()方法中去即可。换句话说就是要避免在类还未初始化完成时从内部实例化该类或在初始化过程中引用还未初始化的字段。

写在最后

静下浮燥之心,仔细思量自己是否真的掌握了本文主题所引出的知识,如果您觉得您已经完全或基本掌握了,那么很好,在最后,我将前面的代码稍做下修改,请思考下面两组程序是否同样会存在问题呢?

程序一

public class CachingEnumResolver {
 public static Map CODE_MAP_CACHE;
 static {
CODE_MAP_CACHE = new HashMap();
//为了说明问题,我在这里初始化一条数据
CODE_MAP_CACHE.put("0","北京市");
initEnums();
 } 

程序二

public class CachingEnumResolver {
 private static final CachingEnumResolver SINGLE_ENUM_RESOLVER;
 public static Map CODE_MAP_CACHE;
 static {
CODE_MAP_CACHE = new HashMap();
//为了说明问题,我在这里初始化一条数据
CODE_MAP_CACHE.put("0","北京市");
SINGLE_ENUM_RESOLVER = new CachingEnumResolver();
initEnums();
 } 

最后,一点关于JAVA群体的感言:时下正是各种开源框架盛行时期,Spring更是大行其道,吸引着一大批JEE开发者的眼球(我也是fans中的一员)。然而,让我们仔细观察一下--以 Spring 群体为例,在那么多的Spring fans当中,有多少人去研究过Spring 源代码?又有多少人对Spring 设计思想有真正深入了解呢?当然,我是没有资格以这样的口吻来说事的,我只是想表明一个观点--学东西一定要"正本清源"。

献上此文,谨以共勉。

(责任编辑 火凤凰 sunsj@51cto.com  TEL:(010)68476636-8007)



共4页: 上一页 [1] [2] [3] 4
【内容导航】
发表
查看
我也说两句

匿名发表

(如果看不清请点击图片进行更换)


中 国 领 先 的 IT 技 术 网 站 ·
技 术 成 就 梦 想
·Java基础教程 (查看52371次)
·UML类图详解 (查看46839次)
·Java编程开发手册 (查看25118次)
·UML统一建模语言 (查看24099次)
·C#技术开发指南 (查看22406次)
·Java编程开发手册 (1195个砖)
·Java基础教程 (429个砖)
·C#技术开发指南 (304个砖)
·PB开发教程 (220个砖)
·.NET开发手册 (217个砖)
·Java编程开发手册 (653个好)
·Java基础教程 (569个好)
·.NET开发手册 (251个好)
·PB开发教程 (209个好)
·Delphi开发技术手册 (174个好)
订阅技术快讯
电子杂志下载
名称:网络安全精品应用黄皮书
简介:《2007精品网络安全黄皮书》包括了9个大类24个小类, 800余篇文章,内容包含了熊猫烧香病毒、DDOS攻击、ARP病等热点问题的介绍及解决方案。从病毒查杀、防范、系统、数据等各方面的安全设置到黑客技术的了解、防范,涉及到了安全应用的全部领域, 由浅至深内容全面。
名称:Vista精品应用黄皮书
简介:《Vista精品应用黄皮书》囊括了Vista的各方面内容。此次的精简版,是将里面的内容做了提取,便于用户下载和使用。内容包含了各种Vista的安装与实施、技巧与解析以及各种Vista相关学习文档和相关软件的安全下载。该电子书是了解和应用Vista人员必备的工具手册,并且也是第一本
名称:2006中国IT论坛精品集合
简介:本书由“51CTO论坛推广联盟”制作完成。书中所有内容均来自各联盟成员的论坛(网站)。制作本书的目的是为了集中大家的优势资源,将更多更精彩的内容带给广大技术爱好者。本书是联盟成立以来制作的第一本书。
关键字阅读
频道精选
主编信箱 热线:010-66476606 告诉我们您想看的:专题 文章
关于我们 | 诚聘英才 | 联系我们 | 网站大事 | 意见反馈 | 网站地图
Copyright©2005-2007 51CTO.COM 版权所有