Java语言和编程环境的设计用于解决现代编程中的许多问题。它起源于一个大项目中的一部分,以开发用于电子出版的高级软件。这些设计是一些小的,可靠的,可移植的,分布的,实时嵌入系统。当我们开始这个项目时,我们打算使用C++,但我们遇到了一些问题。开始仅是一些编译技术问题,但随着时间的推移,我们遇到了一些最好通过更改语言才能解决的问题。
随附的文章,“HotJava浏览器:白皮书”,描述了一个强大的展示Java语言功能的应用程序。
Java:一个简单的,面向对象的,分布的,解释的,健壮的,安全的,中立于体系结构的,可移植的,高性能的,多线索,以及动态的语言。
一种提取某一系统特征的方法是采用一些零散的单词。我们用一标准集合来描述Java,本章的其它部分揭示了哪些零散单词的含义以及我们试图解决的问题。
Archimedes公司是一个假象的软件公司,它生产基础物理的教学软件。这个软件被设计成同用户交互,不仅提供传统课本方式的文字和说明,而且提供一组软件实验室平台,以在上面建立试验和模拟行为。例如,最基本的情况是允许学生将杠杆和滑轮放在一起,看他们是怎样动作的。用斜体字描述Archimedes的设计者所面临的的尝试和困难,用于提供示例所提出语言的概念。
我们期望建立一个系统,使得人们不必进行很多神密的训练就可以很容易的编程,并且支撑今天的标准的实践。目前工作的大多数程序员使用C语言,做面向对象编程的程序员使用C++。 因此尽管我们发现C++是不合适的,为了使系统更加可以理解,我们将Java设计成尽可能与C++相近。
Java省略了C++中许多很少使用的,很难理解的,含混的特征,经验表明这些特性带来了更多的不幸而不是益处。这些省略的特征主要包括算符重载(尽管Java员使用方法重载),多继承,以及扩充的自动系数。
我们增加的自动垃圾回收,以此简化Java编程的任务,但是使系统有点更加复杂。在C和C++应用中的一个很好的通用的复杂性的例子是存储管理:内存分配和释放。通过自动垃圾回收的优点,Java语言不仅使程序设计任务更容易,而且戏剧般地减少了错误。
Archimedes中的人们希望花时间考虑杠杆和滑轮,但是反而在通常的编程任务上花很多的时间。他们擅长的技术是教课而不是编程。这些编程任务中最复杂的情况是在20K的代码行中计算出内存在那里消耗的。
简单的另一方面是小巧,Java的另一个目标是使软件的构造能够在小的机器上独立运行。基本的解释器和类支持的代码大小是在40K字节左右;所增加的基本的标准库和线索支持(尤其是自包含的微核)增加了额外的175K。
不幸的是这是工业上最过多使用的零散单词之一。但面向对象的设计是非常强大的,因为它方便了清晰地定义接口,并且对于提供可重用的“软件IC”成为可能。
简单地说,面向对象的设计是关注数据(=对象)和接口的技术。与木匠相似,一个“面向对象”的木匠更关心所建造的椅子,其次是工具:一个“非面向对象”的木匠将主要考虑它的工具。面向对象的设计也是定义模块怎样“即插即用”的机制。
Archimedes中的人们在他们的模拟中拥有许多东西,其中有绳子和松紧带。在他们初始的C版本的产品中,他们以一个漂亮的大系统结束,因为他们不得不为描述绳子与松紧带写不同的软件。当他们重新以面向对象的风格写他们的应用程序时,他们发现可以定义一个基本的对象,以代表绳子与松紧带的公共的特性,然后将绳子与松紧带定义为基本类型的变种(子类)。当到增加链子的时候,就是很容易的事了,因为他们可以在前面所写的程序上建立,而不是写整个新对象的模拟。
Java有一个扩充的例程库,以方便地复制TCP/IP协议,例如HTTP和FTP。Java应用程序可以通过URL经网络来打开和访问对象,当访问局域文件系统时,程序员也可方便地使用它。
Archimedes中的人们起初为CD ROM建立他们的东西,但是他们有一些想法,以进行他们所期望的为下一代产品尝试交互的学习游戏。例如,他们想要允许在不同机器上的学生合作建立被模拟的机器。但他们所看到的所有的网络系统是复杂的而且需要神秘的软件专家。因此他们放弃了。
Java用于写在不同方面上都必须是可靠的程序。Java将许多重点放在早期检查可能的错误,然后动态检查(运行时间),并且减少易于出错的情况。
一个强有力的类型语言(象C++)的优点之一是他允许扩充的编译时间检查,使得尽早地发现错误。
连接器理解类型系统而且由编译器重复检查众多的类型,从而保护版本不匹配的问题。 Java与C/C++最大的不同是Java有一个指针模型,这减少了内存覆盖和数据毁坏的可能性。Java用真正的数组以替代指针算法。这允许执行下标检查。另外,不可能将任意的正数强制转换成指针。
Archimedes中的人们将他们的工作基本上以C的方式快速的工作。但是他们的时间表因一些小的错误而在不断的流逝,他们有许多麻烦:内存崩溃,版本不一致和接口不匹配。 由于C使他们在他们的代码中打了一些补丁,他们须支付保证质量的时间。他们不得不因错误而在第一个版本之后重新发布他们的软件。
然而Java并不使QA问题消失,而是使他更加的简单。
象Lisp,TCL和Smaltalk的动态语言是经常用于原型开发。他们成功之一是他们很健壮:你不必担心内存的释放和崩溃。程序员可以相对的不害怕内存的处理,因为他们不必担心他崩溃。Java存在这个特性而且是很自由的。
动态语言适合于原型开发的一个原因是他们不要求过早地定出决策。Java存在相反的特性;他强迫你明显的作出选择。 与这些选择一起,有许多帮助:你可以写一个方法请求,如果你使某些事情出错,在编译时间会通知你。你不必担心方法请求错误。通过接口代替类,你也可以得到许多灵活性。
Java目标是用于网络/分布环境。针对此目标,在安全性上放了许多重点。Java允许构造无病毒、无仿照的系统。鉴定技术是基于公开密钥加密。
在“健壮”和“安全”之间存在一个很强的交互作用。例如,对指针文法的改变,使得应用程序不可能伪造对数据结构的访问或者对对象中私有数据的访问,此对象是不可访问的。由此关上了大多数病毒活动的大门。
有人写了一个有趣的对Archimedes系统的PC版本的“补丁”。他们将这个补丁邮寄到一个主要的公告牌上。由于很容易获得以及在系统上增加一些有趣的特征,许多人下载它。Archimedes的人们还没有检测它,它就象在工作。直到下一个四月一日,数千名的员工发现在他们的孩子课本上弹出粗鲁的画片。不用说,尽管他们没有方法负责这个偶然事件,Archimedes的人们仍有许多要控制的损坏。
Java设计成支持网络上的应用程序。一般地,网络包含各种不同的系统,它们带有不同的CPU和操作系统体系结构。为了允许一个Java程序能在网络上的任何地方执行,编译器产生一个体系结构中性的目标文件格式—编译代码可以执行在许多处理器上,只要存在Java运行时间系统。
这不仅有益于网络,而且有益于单一系统软件的分布。在目前的个人计算机市场,应用程序编写这不得不编写与IBM PC和Apple Macintosh兼容的版本。由于PC市场(通过Windows/NT)使许多CPU体系结构多样化,以及Apple从68000移到Power PC,这使得编写能在所有平台上运行的软件几乎是不可能的。通过Java,应用程序的同一版本可以在所有平台上运行。
Java编译器通过产生字节代码指令来完成,此字节代码与专门的计算机体系结构无关。进一步,他们设计成很容易地在任何机器上解释和自由地翻译成内部机器码。
Archimedes是一个小的公司。他们开始编写PC机上的软件,因为它是最大的市场。不久,他们成为一个足够大的公司,他们能够负担的起移植到Macintosh,但是那是一个非常大的工作,不能得到补偿的。他们不能负担移植到Power PC Macintosh或者MIPS NT机器。他们不能“抓住浪尖”,由此发生,竞争者,…
体系结构中性是最大的可移植性,但是还有更多。不想C和C++,它不存在“依赖于实现”的说明。说明了原始数据类型的大小,以及在其上的算法的行为。例如,“int”总是意味着有符号的两个互补的32位整数,而且“float”意味着一个32位IEEE754浮点数。在今天做这些选择是可行的,因为基本的所有流行的CPU都共享这些特性。
库,作为系统的一部分,定义了可移植接口。例如,存在一个抽象的窗口类,在Unix,Windows,Macintosh上实现它。
Java系统本身是极其可移植的。新的编译器是用Java编写,而且运行时间是用带有清晰可移植性边界的ANSI C编写。可移植性边界主要是POSIX。
Java解释器可以直接在任何机器上执行Java字节代码,解释器已移植到此机器上。由于链接是一个递增的和轻量进程,开发进程可以更快和外在的。
作为字节代码流的一部分,携带了更多的编译时间信息,而且可以在运行时间获得。这就是链接器的类型检查所基于的,也是RPC协议推导所基于的。也是的程序更加服务于调试。
Archimedes中的程序员花费许多时间以等待程序编译和链接。他们也花费许多时间来跟踪无意识的错误,因为有些变化的源文件并未编译(无论是否是用漂亮的“make”工具),这会引起版本不匹配;他们不得不跟踪在程序中的不同部分不一致声明的过程。在时间表上损失了另外两个月。
要解释的字节代码的性能通常是足够的,然而有些情况需要高性能。可以将字节代码自由地(在运行时间)翻译成机器代码,此机器代码针对于应用程序运行其上的专门的CPU。为了适应于正常的编译器和动态装载器的设计,这有点象在动态装载器中放入最终的机器代码产生器。
字节代码格式设计成与产生机器代码一起考虑,因此实际产生机器代码的过程通常很简单。产生相当好的代码:当它产生字节代码时,它自动地注册分配,而且编译器做一些优化。
在Sun Microsystems SPARCStation 10上被解释代码中我们获得每秒300000方法调用。字节代码转换成机器代码后的性能几乎与内部C或者C++没有区别。
当Archimedes启动时,他们在Smalltalk中作原型。这使投资者感到他们已资助了,但并没真正帮助他们产生它们的代码;为了使他们的模拟足够地快,使系统足够地小,它不得不重新用C编写。
在围绕我们的世界中有许多事情同时进行。多线索是用多个线索构造应用程序的方法。不幸的是,编写处理许多同时发生事件的程序要远比编写传统单线索C和C++风格困难。
Java有一个复杂的同步原语集,它基于广泛使用的由C.A.R.Hoare介绍的监控和条件变量风格。通过将这些概念集成到语言中,它们变得更加易于使用和更加健壮。这种集成的许多风格来源于Xerox's Cedar/Mesa 系统。
多线索的其它优点是更好的交互响应和实时行为。这时有限的,然而,通过基础的独立平台,Java运行时间环境有很好的实时行为。运行在其它系统之上,如Unix,Windows,Macintosh,Windows NT限制了实时响应那个基础系统。
在他们的模拟中许多事件同时进行。拖拉绳子、转动轮子、摆动杠杆、和处理从用户的输入。因为在一个单线索形式中他们不得不写出所有这些,同时发送所有事件,尽管它们彼此无关,也不得不手工混合。使用一个“事件循环”使得更加清晰,但是仍旧混乱。系统变得脆弱和难于理解。他们从所有网上输入数据。但是出示它们一次做一块。这个串行网络通信是很慢的。当他们转换为多线索风格,可以平常地覆盖所有网络通信。
在许多方面,Java是比C或者C++更加动态的语言。它设计成适应于发展的环境。例如,在编程环境中使用C++的一个主要问题是实现代码方式的副作用。如果公司A编写一个类库(一个即插即用组件库),公司B购买它和在他们的产品中使用它,那么如果A改变了它的库并且分发了新的版本,B将几乎当然地不得不重新编译和从新分发它们自己的软件。在一个环境中,最终用户独立地得到A和B的软件(如A是一个OS供应商,B是一个应用程序供应商)会导致问题。
例如,如果A分发了它的库的升级版本,那么所有来自B的软件会断开。在C++中也可能避免这个问题,但是那是极其困难的,它意味着不直接使用语言的任何OO特征。
Archimedes从3DPC Inc中使用面向对象的图形库来构造它们的产品。3DPC发布了一个图形库的新版本,几家计算机制造商将其捆绑到他们新的机器上。购买这些新机器的Archimedes的客户沮丧地发现他们的旧软件不再工作。(在真实生活中,这仅会在Unix系统上发生。在PC世界,3DPC永远不会发布这样的库:他们有能力改变它们的产品,而且严重阻碍了使用C++的面向对象的特征)。
通过建立随后模块之间的互连,Java完全避免这些问题,而且更加利用面向对象的风格。库可以自由地添加新方法和实例变量,而在他们的客户上没有任何影响。
Java理解接口——一个从类似一个类的Objective C借用的概念。接口是一组相应于一个对象的一组方法的简单的说明。它不包含任何实例变量或者实现。接口可以多继承(不象类),并且可以更加灵活地使用它们,而不是通常的僵硬的类继承结构。
类有一个运行时间表示:存在一个名为Class的类,它是包含运行时间类定义的实例。如果,在C或者C++程序中,你有一个对象的指针,但是你不知道对象的类型,就没有方法找到。然而,在Java中,基于运行时间类型信息的查找是直接的。因为在编译时间和运行时间都检测强制类型转换,你可以相信Java中的一个强制类型。另一方面在C和C++中,编译器相信你在做正确的事情。
也可以通过给出一个包含它名字的字符串来查看一个类的定义。这意味着你可以计算一个数据类型名,并且使它很容易地动态链接到运行时间系统中。
为了扩展它们的收入流,在Archimedes中的人们希望设计它们的产品,使得能够加入新的市场后的插入模块以扩充系统。在PC上这是可能的,但是,几乎不能使用。他们不得不雇用一组新的程序员,因为它太复杂。这也给调试增加问题。
Java语言提供了一个强大的程序员所拥有的附加工具。Java使编程更加容易,因为被编译的Java代码是体系结构中性的,Java应用程序是象internet这样的不同环境的理想程序。对于更详细的信息发送邮件到Hotjava@java.sun.com.
Copyright: NPACT