2006 年 12 月 14 日
Apache Harmony 是 2005 年 5 月公布的开放源码 java SE 实现,本文是由 5 部分组成的 进入 Harmony 世界 系列文章的第四篇,这个系列主要介绍 Apache Harmony 项目的内部实现,最新发展现状和开源 Java 开发的模式,并鼓励和欢迎大家参与到 Harmony 的社区中来。
本文较具体地介绍了 Harmony 项目类库(API库)开发过程当中的经验,从架构设计和软件工程的角度,介绍了类库开发过程当中积累的类库模块的划分、测试优先的开发模式、结对编程、代码审核等等最佳实践。
类库模块划分
类库模块的划分,是 Harmony 项目类库总体设计上的主要特点。通过将庞大的 J2SE 类库划分为若干个相对独立而且小规模的功能模块,Harmony 的开发者简化了类库实现的过程,降低了开发类库的风险。类库模块的划分原则和具体划分方式,是项目进行和结构设计实践当中不断总结和归纳出来的。
Harmony 模块化背景和目标
实现一个完整的兼容的开源 J2SE,这是一种很棒的开创性的想法,但它的实现有着相当的难度,有很多的问题需要注重。开源软件的开发流程,具有一定的自由性和不确定性。通常的情况是,来自世界各地的开发者,在一个组织的统一协调下,分工合作,不定期的提交一些功能模块,然后集成到一个大的平台产品当中。这样的开发方式是开源软件的固有特征,但是对于 J2SE 这样的庞大体系,这样的开发模式会增加产品的风险。为了减小风险,便于平台的升级和维护,就要充分考虑以下问题:合理的划分平台,定义好模块之间的接口,以及降低耦合性。总结来说有以下几个目标:
符合 J2SE 基本结构
与现有的 J2SE 实现功能上兼容的同时,在基本的大的组件方面也要做到一致。如 JVM、类库、JIT 组件等等大规模组件必须对应一致。这样可以使 Java 类库的开发工作易于治理,开源社区的参与者可以集中开发他擅长的模块。
独立开发
为了开发的便利和风险的降低,平台的模块必须实现独立开发,各个模块之间尽量减少耦合,这样才可以发挥开源项目的优势,避免其缺陷。
模块替换
在 Java 的开源世界里,随时都有很多开源软件的出现,假如出现了某些优秀的开源 J2SE 组件,应该答应它们方便的替换进来;另外,假如发现本身某一个模块实现上的不足,也可以方便的替换出去,而不影响整个平台。
共享组件
除开提供完整的 J2SE 实现,这个项目的另外一个有价值之处就是在于为开源社区提供共享的 J2SE 组件。这个目标十分重大,因为一个完整的 J2SE 平台,本身就意味着了聚集了很多有价值的组件。所以,平台的设计必须确保这些组件可以方便的被共享和重用。
针对以上目标,在 Harmony 项目中采用了模块化的划分方式。在 Sun 公司的最初设计里面,根本没有考虑过对 Java 模块化,也没有开源的想法,所以原有的耦合性是比较大。而且,这个划分既要有全局的划分,即把整个 J2SE 划分为几个大的组件,如 JVM,API 类库,Tools 等等,也有对组件内部的划分,例如把类库进一步划分成一些模块,不同的模块实现不同的功能。
类库设计
完整的 J2SE 平台的模块化设计,首先应该在最抽象的层次,按照设计目标,划分出整体的模块组件,规定好它们的互联规范,比如对类库、虚拟机间接口的定义;然后,应该在比较具体的层次,在比较大的组件当中再次划分子模块,例如类库的进一步划分。
类库(Class Library)是 J2SE 当中最复杂和最常用的部分。它为 Java 开发者提供了丰富的编程接口,给 Java 应用程序提供了基础类库。Harmony 类库的目标,是要实现一个标准 J2SE 类库,和现有的 Sun 的 JDK 兼容一致。虽然不会增加特性,但是在完全不涉及 Sun 的源代码的前提下,仅仅依靠公开的 Java 文档,设计和开发这样的类库,依然是一项艰巨的工作。
Harmony Class Library 分为三十多个模块。假如我们从上下层次上看,它们主要上分为以下四个大类,主要模块如图所示。
图一 类库划分总图
点击查看大图应该注重到,这个划分和 Sun 公司的 J2SE 结构图并不相同,这是因为,Harmony 为自己项目的特点,对已有的基于包(package)的类库结构按照功能重新分析和归类,有的模块是从包中划分出来,如 instrument 模块做 Java 虚拟机的类重定义和治理功能,它本来是 java.lang 包当中的子包,但是由于功能的独特,所以就被单独分为一块。
下面逐一介绍这四大类和主要的模块。
基础模块 (LUNI) 与 NIO
LUNI 是 Lang、Util、Net、IO 这些模块的首字母总称,他们和新的 NIO 模块一起表示类库的基础和核心部分,处于类库的底层。当然,LUNI 当中也有些独立分出模块的子包,如 instrument,management 模块,这些模块作为虚拟机监测工具类库,就不属于 LUNI。
之所以要把 LUNI 和 NIO 同看作为基础模块,是因为它们互相之间有着密切的联系。在实际实现中,它和 IO 和非常多的底层公用,两者有紧密的联系。如 NIO 当中的 SocketChannel 和 NET 中 Socket 基本上就可以共用同一套底层代码。