类的初始化和对象初始化是 JVM 管理的类型生命周期中非常重要的两个环节,Google 了一遍网络,有关类装载机制的文章倒是不少,然而类初始化和对象初始化的文章并不多,特别是从字节码和 JVM 层次来分析的文章更是鲜有所见。 本文主要对类和对象初始化全过程进行分析,通过一个实际问题引入,将源代码转换成 JVM 字节码后,对 JVM 执行过程的关键点进行全面解析,并在文中穿插入了相关 JVM 规范和 JVM 的部分内部理论知识,以理论与实际结合的方式介绍对象初始化和类初始化之间的协作以及可能存在的冲突问题。 问题引入 近日我在调试一个枚举类型的解析器程序,该解析器是将数据库内一万多条枚举代码装载到缓存中,为了实现快速定位枚举代码和具体枚举类别的所有枚举元素,该类在装载枚举代码的同时对其采取两种策略建立内存索引。由于该类是一个公共服务类,在程序各个层面都会使用到它,因此我将它实现为一个单例类。这个类在我调整类实例化语句位置之前运行正常,但当我把该类实例化语句调整到静态初始化语句之前时,我的程序不再为我工作了。 下面是经过我简化后的示例代码: [清单一] package com.ccb.framework.enums; import java.util.Collections; import java.util.HashMap; import java.util.Map; public class CachingEnumResolver { //单态实例 一切问题皆由此行引起 private static final CachingEnumResolver SINGLE_ENUM_RESOLVER = new CachingEnumResolver(); /*MSGCODE->Category内存索引*/ private static Map CODE_MAP_CACHE; static { CODE_MAP_CACHE = new HashMap(); //为了说明问题,我在这里初始化一条数据 CODE_MAP_CACHE.put("0","北京市"); } //private, for single instance private CachingEnumResolver() { //初始化加载数据 引起问题,该方法也要负点责任 initEnums(); } /** * 初始化所有的枚举类型 */ public static void initEnums() { // ~~~~~~~~~问题从这里开始暴露 ~~~~~~~~~~~// if (null == CODE_MAP_CACHE) { System.out.println("CODE_MAP_CACHE为空,问题在这里开始暴露."); CODE_MAP_CACHE = new HashMap(); } CODE_MAP_CACHE.put("1", "北京市"); CODE_MAP_CACHE.put("2", "云南省"); //..... other code... } public Map getCache() { return Collections.unmodifiableMap(CODE_MAP_CACHE); } /** * 获取单态实例 * * @return */ public static CachingEnumResolver getInstance() { return SINGLE_ENUM_RESOLVER; } public static void main(String[] args) { System.out.println(CachingEnumResolver.getInstance().getCache()); } } 想必大家看了上面的代码后会感觉有些茫然,这个类看起来没有问题啊,这的确属于典型的饿汉式单态模式啊,怎么会有问题呢? 是的,他看起来的确没有问题,可是如果将他 run 起来时,其结果是他不会为你正确 work。运行该类,它的执行结果是: [清单二] CODE_MAP_CACHE为空,问题在这里开始暴露.{0=北京市} 我的程序怎么会这样?为什么在 initEnum() 方法里 CODE_MAP_CACHE 为空?为什么我输出的 CODE_MAP_CACHE 内容只有一个元素,其它两个元素呢????!! 看到这里,如果是你在调试该程序,你此刻一定觉得很奇怪,难道是我的 Jvm 有问题吗?非也!如果不是,那我的程序是怎么了?这绝对不是我想要的结果。可事实上无论怎么修改 initEnum() 方法都无济于事,起码我最初是一定不会怀疑到问题可能出在创建 CachingEnumResolver 实例这一环节上。正是因为我太相信我创建 CachingEnumResolver 实例的方法,加之对 Java 类初始化与对象实例化底层原理理解有所偏差,使我为此付出了三、四个小时--约半个工作日的大好青春。 那么问题究竟出在哪里呢?为什么会出现这样的怪事呢?在解决这个问题之前,先让我们来了解一下JVM的类和对象初始化的底层机制。 类的生命周期
图展示的是类生命周期流向;在本文里,我只打算谈谈类的"初始化"以及"对象实例化"两个阶段。 类初始化 类"初始化"阶段,它是一个类或接口被首次使用的前阶段中的最后一项工作,本阶段负责为类变量赋予正确的初始值。 Java 编译器把所有的类变量初始化语句和类型的静态初始化器通通收集到
推荐内容
- 08-25Java应用:Fedora Linux 8系统
- 07-30源码分享:蜘蛛抓取淘宝
- 07-30AJAX 开发的两种不同的方法
- 07-30IT行业培训必读 优秀程序
- 07-30J2EE面向对象
- 07-30JAVA的事件处理机制
- 12-02JAVA-MyEclipse 自动提示(按
- 12-02一些关于中文乱码问题的
- 07-30AIX字体丢失——解决方案
- 08-25Java应用:Fedora Linux 8系统
- 07-30Security
- 02-23用Java构造自己的媒体播放
- 01-05深入浅出Java堆的管理--垃
- 02-21Java Robot对象实现服务器屏
- 07-30用JavaFX写用户界面控制器
- 11-17让Java说话
解析Java类和对象的初始化过程
时间:2006-09-25 作者: 点击: 2次 来源:
类的初始化和对象初始化是 JVM 管理的类型生命周期中非常重要的两个环节,Google 了一遍网络,有关类装载机制的文章倒是不少,然而类初始化和对象初始化的文章并不多,特别是从字
dedecms.com
复制地址和好友共享 相关创意
我喜欢
(0)
0%
没意思
(0)
style="width:0%"
0%
| 上一篇:JAVA 7新特性让JVM“瘦身”成功! | ↑上帝请打分↑ | 下一篇:经典:Java及相关字符集编码问题研究 |










