Java 之父 James Gosling 最新访谈:JIT 很好,但不适合所有语言
计算机编程确实是一门艺术。James Gosling,“Java 之父”, 完成了 Java 的原始设计,并实现了 Java 最初版本的编译器和虚拟机。90年代初,James Goslin...
计算机编程确实是一门艺术。
James Gosling,“Java 之父”, 完成了 Java 的原始设计,并实现了 Java 最初版本的编译器和虚拟机。
90年代初,James Gosling和一群技术人员合作“绿色计划”,创建了一个名为Oak的项目,旨在开发出能够运行于虚拟机的编程语言,开创计算机在家电产品上的嵌入式应用。后来,这项工作就演变为Java。
1996年1月,Sun公司发布了Java的第一个开发工具包;
1997年2月,JDK 1.1面世;
1998年12月8日,第二代Java平台的企业版J2EE发布;
2000年5月,JDK1.3、JDK1.4和J2SE1.3相继发布;
.......
(详细版本历史,参看本文后面的附录2部分.)
随着互联网的普及,Java成为全球最流行的开发语言。James Gosling也因此被称作“Java之父”。
James Gosling 在此次访谈中聊了大量关于编程语言的话题,例如对现代编程语言新特性的看法、怎么看待编程语言更新后引起的破坏性变更、为什么不是所有编程语言都使用 JIT 技术等。
Evrone 是一家企业软件开发公司,旗下担任技术布道师 (DevRel) 的 Grigory Petrov 最近对 James Gosling 进行了采访。
James Gosling 在此次访谈中聊了大量关于编程语言的话题,例如对现代编程语言新特性的看法、怎么看待编程语言更新后引起的破坏性变更、为什么不是所有编程语言都使用 JIT 技术等。
在采访中,James提出了许多观点,他认为:“对软件的可靠性要求越高,静态类型语言就越有帮助。”他还分享了自己对某些编程语言的看法:反感C语言中的宏、对Lombok又爱又恨、很喜爱Lisp等等。
关于现代编程语言的构建方式
Grigory:作为软件开发人员和软件顾问,我们试图在俄罗斯组织Python、Ruby、Java和Go社区。您在Java方面的经验和工作可以很好地帮助开发人员。通过这次采访,我们希望能够帮助到其他开发者,一起解决业内的基本问题。
有些语言,比如Go,没有类和继承一说,而另一些语言则尝试使用诸如Rust的特性。作为一名语言设计师,您认为现代通用的、合理的编程语言构建方式应该是什么?
James:我应该会继续使用类,类对我的编程工作很有用。在C语言中有一些宏,这非常糟糕,因为宏不是语言的一部分,不应该纳入其中。而Rust的工作人员正在尝试恰到好处地使用宏。
对于其他语言,如Lisp家族,人们总是设法更灵活地应用它们。它们有一种定义语法的方法,语法几乎完全与语义无关。在大多数语言中,语法和语义是密切相关的。我曾写了很多Lisp,我真的很喜欢使用Lisp程序。有的语言能让你以不同的方式做到这一点,比如在Groovy中,你可以直接使用AST,Rust有一些语法集成的宏。但我总觉得还有一个问题:除此之外还能做什么呢?
Lisp对代码片段进行运算,再生成新代码,在Java世界里,人们就是这样做的。虽然看似低级,但很受欢迎。人们可以使用注释的组合,用一些不同的语言生成字节码,这是超级强大的。它会给你意想不到的惊喜,比如在Jackson,它通过计算序列化程序延展了性能。
一方面,这是一种非常强大的技术,另一方面,它非常难以驾驭。这个技术充满可能性,但这种可能性是有限的。我对Lombok又爱又恨,因为它添加了一大堆Java特性,这些特性都很不错,但从另一方面来说,也显示出了弱点。JCP的社区职能在下降,我已经离开好几年了,虽然有些事情可以做,但也只能是在纸上谈谈。
Grigory:这就是为什么我们更想了解您创建语言的经验,而不是一些Java增强建议。五年前,我尝试操控一些Java字节码。我发现,用它来创建特定领域的语言有点困难。但是有了Ruby后,就容易多了。Evrone公司有许多精通Ruby的开发人员。Ruby开发人员很优秀,但是他们需要多年的培训才能真正掌控DSL的魔力。
James:像代码片段运算这样的特性,在Java中之所以尴尬是因为Java总是试图去编译机器代码,Ruby几乎总是被解释。如果你想同时获得超强功能和终极性能,这一切就会变得很困难。
如何看待那些破坏性的更改?
Grigory:最近,我们采访了Ruby的创作者Yukihiro Matsumoto,他对最新的Ruby 3.0版本进行了实验,试图在不破坏更改的情况下发布这个版本。我知道Java对“不破坏更改”的态度一直很谨慎。让所有语言在完全兼容的情况下进化,这是合理的吗?还是说这个方法只能用于特定的语言,例如Ruby或Java?
James:这几乎完全取决于开发人员社区的规模。每一个破坏性的变更都会给开发人员社区带来痛苦。如果你没有很多的开发人员,那么破坏更改并不是一个大问题。
除此之外,你还必须权衡成本效益。如果你做了一个突破性的改变,它会增加你的工作负担,但也可能会带来一些好处。不过,如果你只是将下标操作符从方括号更改为圆括号,这并不会带来任何好处,只会徒增麻烦。
在JDK 9中,出现了一个罕见的破坏性变化:如果你使用的是隐藏API,封装机制就会被打乱。人们打破封装界限,运用了非常规的方式,使用了不应该使用的东西,这种改变是痛苦的。然而,一旦我们彻底改变,平台便有了更多的创新空间。在这种改变下,平台可以被分割,你可以定制打包,Java的运行环境就会更小。
另一个麻烦是:当遇到Bug时,人们会为之做一些变通措施,如果你修复了这个Bug,变通措施就被破坏了。在Java的世界中,确实有这样的例子,我们要么不修复Bug,要么引入一个方法来修正错误,这甚至体现在硬件上。
如何看待静态类型检查器?
Grigory:25年前,当我开始自己的软件开发生涯时,我写了很多C和C++代码。几乎每个月都会遇到一次错误警报。调试这些错误是一件很痛苦的事情。但是现在,我看到许多工具集成到我们的工作流程中,比如静态类型检查器。现代开发人员使用IDE,如NetBeans、IntelliJ IDEA,甚至Visual Studio。他们编写源代码,编写静态类型检查器解析程序,构造抽象语法树,并进行检查,然后在文本编辑器中标记错误。这些技巧不仅适用于静态类型的语言,也适用于动态类型的语言,在Python、Ruby和TypeScript中皆可使用。
你对静态类型检查器有什么看法?它们能帮助人们编写出更好的程序,还是说需要在语言语法中添加更多内容?
James:我都同意。我非常喜欢使用静态类型系统的语言,因为它们为静态类型检查器和IDE提供了一个框架。作为一名资深软件工程师,寻找那些奇怪的Bug是最浪费时间的。为减少这方面的时间浪费,我会尽力阻止Bug的出现。因此,我非常喜欢IDE,它能够提供减少Bug的方法。而动态类型语言很少有框架来解决这个问题,因为它们不一定能判断所有类型,只能靠猜测。强类型语言(如Java)为类型检查器提供了更严格的框架。在另一个层次上,甚至可以进行自动的定理证明。像Dafny这样的系统,它有一个非常复杂的定理证明器。所以如果你想建立一个加密算法,你将能够用数学方法进行证明。这听上去很夸张,但对于某些代码来说,真的很有用。
这很大程度上取决于你的目标是什么。
如果你是一名正在努力完成作业的大学生,或是一名正在努力毕业的博士生,那么当你编写一个程序时,你的目标是让这个程序至少能运行一次,因为你必须要展示成果。
如果你在行业环境中,那么每次运行都必须成功。一次运行成功和每次都运行成功之间的差别是巨大的。如果只需要运作一次,那么动态语言会更合适。如果你必须确保它能一次又一次地运行,那么所有的静态类型工具都适用。
如果你是一个物理学家,你想得出一些计算结果,那么它只需要运行一次。这取决于你的工作背景。你对软件的可靠性要求越高,静态类型语言就越有帮助。
现在是开源软件的黄金时代吗?
Grigory:我们来谈谈企业和产业发展吧。我从来没做过机器人,但我曾在大型开发公司工作过,如果将今天和20-25年前进行比较,我们会发现,像GitHub这样的社交编码平台,得到了大公司的支持,他们帮助个人开发者和企业软件开发者进行开源开发。那么,现在是不是开源软件的黄金时代呢?你有何看法?
James:我不知道。这个问题涉及未来。“现在是黄金时代吗?”背后的意思是,将来要开始走下坡路了吗?如果现在是黄金时代,那么未来就不是黄金时代了吗?
我认为我们一直都在迈向黄金时代,依然在不断改进。目前,我们依然有各种各样的安全问题,网络攻击不断,因此我不保证这是黄金时代。如果有一种方式,可以终结网络安全隐患,那将是非常好的。现在确实是个好时机,但还可以更好。
为什么有的语言不使用JIT?
Grigory:您使用JIT(即时编译)创建了Java和JVM。JIT保证了高速,同时保持了高级语法。许多语言都跟随你的脚步,比如C#和JavaScript。其他语言,如Python、Ruby、PHP,都有可选的JIT,但不太常用。许多主流语言也并不使用JIT来提升速度。为什么不是所有的语言都使用JIT呢?他们不想为软件开发人员提供更快的速度吗?
James:如果开发者想要获得性能改进,那么使用静态类型语言是非常有用的。通常,人们会给语言添加注释,就会得到TypeScript这样的语言,TypeScript的本质就是带有类型注释的JavaScript。而JavaScript的本质是Java,只是去掉了类型声明。所以TypeScript本质上就是带有置换语法的Java。
在Python之类的语言中,通常只有一种数值,那就是双精度浮点数。没有真正的整数,没有字节和16位整数这些东西。如果是双精度浮点数和单精度浮点数,概念认知的过程会很复杂,但你必须掌握数值分析。许多软件工程师对数值分析几乎一无所知,所以他们直接放弃了。
如果你是一个使用Python的物理学家,那么精确度对你来说是最重要的。如果你需要在内存中放入一个非常大的数组,在这种情况下,单精度和双精度或8位整数之间的差异就非常重要。
在我的一生中,我参加过许多数值分析课程,被数值分析弄得焦头烂额,因此我不得不关注数值分析。具体问题具体分析,大多数使用脚本语言的人并不关注这类问题。很多人并不关心具体的性能和数值,他们关心的是:“它够快吗?”性能是一个boolean值,对一些人来说,这更像是调试一辆赛车,如果你的车每小时能够行驶两到三英里,你更有可能获胜。
Grigory:几个月前,Ruby on Rails(一种广受欢迎的Web框架)的作者David Heinemeier Hansson提到,在他的云计算的应用开发中,性能基本都是由缓存、消息队列、存储等方面决定的,开发语言的影响最多不超过15%。他指出,不管Ruby有多“慢”,这都不是很重要,因为即使Ruby的速度快了100倍,将15%变成了1%,也不会改变什么。
James:要具体分析你的任务类型。如果你的任务是由网络和数据库等主导的,你一直在做RPC,那么第一步就是质疑这些RPC是否有价值。微服务确实挺不错,但是它们比方法调用慢一百万倍。想想这意味着什么。
对于大多数人来说,他们可以通过清晰的大规模架构来获得更多性能。但对大部分人而言,所有的细节都很重要。如果你知道高并发的重要性,知道它能够同时驱动数千个进程,进行大型计算;如果你做的是数据库或存储服务,你会非常在意这些细节。所以这完全取决于你手头的任务。
关于现代async/await方法
Grigory:许多语言都采用了协程和async/await方法来处理网速慢之类的问题。这个方法被添加到Python、 Ruby、 JavaScript以及其他语言中。但是在一个线程中这个方法并不是无所不能的,并且很复杂,有时还会使软件运行速度变慢。那么,您如何看待这种现代async/await方法呢?这是处理网络的好方法,还是我们误用了它,我们需要寻找其他方法?
James:这依然取决于实际情况。协程是完美的,它起源于60年代。第一种使用协程的语言是Simula 67。Simula是一种很好的语言,它没有线程,但是有协程,只不过它们做协程的方式看起来很像线程。协程完全避开了并行中的一些难题。对我来说,协程有一个问题:它们不允许使用多个处理器,无法做到真正的并行。因此我已经很久没有使用协程。
所以人们更重视那些真正具有并行性的语言,比如Erlang和Java。
在Java中使用ConcurrentHashMap可以做到很多事情。如果你在进行多协程操作又没有足够的处理器,一旦你使用基于协程的语言并使用多个处理器,最后也只是饱和了一个处理器而已。使用多个处理器也是不得已的,毕竟世界上已经没有单位处理器了。每样东西都有很多内核,如果你想在一个问题上同时使用所有的计算机,你只需要克服多线程所固有的复杂性。
还有样式的问题。透明的控制反转时常发生,而你只能被动接受。这会让你的语法看起来很像线程,但也意味着在真正的线程中会遇到一些问题。例如,你输入“a=a + 1”的语句,你知道这个操作不会被中断,所以你不需要同步。但在其他情况下,它变成了一个event导向的样式,操作过程中,你需要插入一个事件处理程序,去处理后续问题。这就是JavaScript的主要风格。这样也不错,但似乎有点笨拙。
70年代早期,我第一次接触Simula,我发现它很灵活,在编码过程中,运算过程几乎是独立的。作为一个概念模型,它要清晰得多。
第一语言的选择
Grigory:我想问一个非技术问题,在你看来,对于现在刚入门的软件开发人员或者是研究生和大学生而言,他们应该选择哪一种语言来作为他们的第一语言?
James:我回答这个问题可能会带有一点偏见,毕竟 Java 已经成功运行这么多年。我学的第一种编程语言是PDP-8汇编代码,随后是Fortran。大家可以去学习任何语言,有些人的接受能力更强,但这很大程度上取决于一个人最终的职业道路。如果你想成为一个软件开发人员,你要构建大型的、高性能的系统,运行在JVM上的语言最值得去学习,例如Scala和Kotlin,Clojure很有趣。如果你是物理专业的学生,Python是个不错的选择。
其实选哪一种语言都无关紧要,很多人都只是坚持他们学到的第一种语言,如果你能让人们反复学习各种语言,那肯定是最好的。我认为每个大学都应该为学生开设一门“编程语言”的课程。用五种不同的程序语言完成作业,这能加快学习进度,并且他们会发现这些语言的区别真的不大,同时也能让他们自己去思考,哪一种语言更好。很久以前我上过一门课,每次作业我都用最不合适的语言,例如,用Cobol语言进行数值计算,以及Fortran中的符号操作。令人惊讶的是,我的成绩依然是A。
如何看待“模式匹配”?
Grigory:下一个问题是关于模式匹配的。最近,它与Python、Ruby接轨,并且为不同的语言提出了建议。我们查阅了开发人员白皮书发现,目前并不能完全确定模式匹配在现代高级语言中的作用。您认为这种模式匹配思想,如何适用于Java、Python、Ruby或其他高级语言?我们真的需要模式匹配吗,或者它是特殊案例的特定用法?
James:对于新手来说,我认为编程语言中的“模式匹配”一词会造成误导。当我听到“模式匹配”这个短语时,我想到的是正则表达式。Simula有inspect语句,而inspect语句与许多模式匹配语句几乎完全相同。inspect语句是一个case语句,其中case标签是类型名,你可以执行:
Inspect PWhen Image do Show;When Vector do Draw;
因此可以把它看成是一个case语句,用case处理类型,大多数模式匹配语言的建议都是这样的。就我个人而言,我很喜欢,特别是应对C的隐形强制转换。在C之类的语言中,常常需要进行强制转换。如果你执行“inspect P When Image P do P ”,那么在case语句体中,P就是switch标签的类型,这让一切都变得简单多了。我很喜欢Simula中的inspect语句。我同意所谓“特殊案例”的说法,如果称之为“模式匹配”,但是它又不如正则表达式,就会有误导性,像一则虚假广告。但是抛开这些,我依然认为它的功能很强大。
可以将所有的语言联系到一起吗?
Grigory:还有最后一个问题。俄罗斯软件开发人员对JetBrains和Kotlin的开发倍感骄傲。Kotlin、Clojure和Scala等语言,在您创建的Java虚拟机、库、框架和现有代码生态系统上蓬勃发展。但是,这些语言都面临着挑战吗?能不能把这些语言都联系到一起呢?当有人试图用不同的语法对Java执行hotswap操作时,会遇到什么困难?
James:这要看你的目的是什么。Java虚拟机内置了许多安全性和可靠性的概念,主要与内存模型的完整性有关,诸如指针之类的东西,因此你不能伪造指针。对于C语言,如果你没有能力伪造,你将无法使用。如果你试图在JVM上实现C语言,并配置了严格的安全虚拟机,有些功能将无法实现。但是有些人所构建的虚拟机并没有严格的安全模型,并且没有内存分配模型。如果想要在C和Kotlin之间实现互操作,就必须放弃一定程度的安全性和可靠性。这就看你的取舍了。
在Java诞生之初,我的原则是:我不想调试内存损坏问题。在内存崩溃问题上我已经浪费了太多的时间,这个问题能消耗你几天的时间。我真的很讨厌追踪内存损坏bug。不过,每个人的喜好不同,可能有人认为花时间做这件事很有价值。也有人喜欢使用vi,在70年代和80年代它都是一个很好的编辑器。
Grigory:内存安全模型确实很重要,它提供了一些东西,但也造成了一些限制。非常感谢你,James!
原文链接:https://evrone.com/james-gosling-interview
附录1: JIT 编译原理
JIT(just in time):即时编译编译器,能够加速 Java 程序的执行速度。通常通过 javac 将java代码编译,转换成 java 字节码,JVM将字节码将其翻译成机器指令,逐条读入,逐条解释翻译。很显然,经过解释执行,其执行速度必然会比可执行的二进制字节码程序慢很多。为了提高执行速度,引入了JIT,它会在运行时把翻译过的机器码保存起来,以备下次使用。
JIT默认是启用的,JVM 读入 .class 文件, 解释后发给JIT编译器,然后它将字节码编译成本机机器代码,下图展示了该过程:
Hot Spot VM 编译
当 JVM 执行代码时,它并不立即开始编译代码。这主要有两个原因:
首先,如果这段代码只会被执行一次,那么编译就是在浪费精力。如果一段代码被多次执行,那么编译就非常值得了。因此,编译器具有的这种权衡能力会首先执行解释后的代码,然后再去分辨哪些方法会被频繁调用来保证其本身的编译。Java代码开始都是被编译器编译成字节码文件,然后字节码文件会被交由 JVM 解释执行,其实Java本身是一种半编译半解释执行的语言。
Hot Spot VM 采用了 JIT compile 技术,将运行频率很高的字节码直接编译为机器指令执行以提高性能(以 method 为翻译单位,还会保存起来,第二次执行就不用翻译了)直接执行。
第二个原因是最优化,当 JVM 执行某一方法或遍历循环的次数越多,就会更加了解代码结构,那么 JVM 在编译代码的时候就做出相应的优化。
把源代码翻译成机器指令,一般要经过以下几个重要步骤:
我们可以把将.java文件编译成.class的编译过程称之为前端编译。把将.class文件翻译成机器指令的编译过程称之为后端编译。
Java中的前端编译
前端编译主要指与源语言有关但与目标机无关的部分,包括词法分析、语法分析、语义分析与中间代码生成。
我们所熟知的javac的编译就是前端编译。除了这种以外,我们使用的很多IDE,如eclipse,idea等,都内置了前端编译器。主要功能就是把.java代码转换成.class代码。
词法分析
词法分析阶段是编译过程的第一个阶段。这个阶段的任务是从左到右一个字符一个字符地读入源程序,将字符序列转换为标记(token)序列的过程。这里的标记是一个字符串,是构成源代码的最小单位。在这个过程中,词法分析器还会对标记进行分类。词法分析器通常不会关心标记之间的关系(属于语法分析的范畴),举例来说:词法分析器能够将括号识别为标记,但并不保证括号是否匹配。
语法分析
语法分析的任务是在词法分析的基础上将单词序列组合成各类语法短语,如“程序”,“语句”,“表达式”等等.语法分析程序判断源程序在结构上是否正确.源程序的结构由上下文无关文法描述。
语义分析
语义分析是编译过程的一个逻辑阶段, 语义分析的任务是对结构上正确的源程序进行上下文有关性质的审查,进行类型审查。语义分析是审查源程序有无语义错误,为代码生成阶段收集类型信息。
语义分析的一个重要部分就是类型检查。比如很多语言要求数组下标必须为整数,如果使用浮点数作为下标,编译器就必须报错。再比如,很多语言允许某些类型转换,称为自动类型转换。
中间代码生成
在源程序的语法分析和语义分析完成之后,很多编译器生成一个明确的低级的或类机器语言的中间表示。该中间表示有两个重要的性质:
1.易于生成;
2.能够轻松地翻译为目标机器上的语言。
在Java中,javac执行的结果就是得到一个字节码,而这个字节码其实就是一种中间代码。
PS:著名的解语法糖操作,也是在javac中完成的。
Java中的后端编译
HotSpot虚拟机中内置了两个JIT编译器:Client Complier和Server Complier,分别用在客户端和服务端,目前主流的HotSpot虚拟机中默认是采用解释器与其中一个编译器直接配合的方式工作。
热点检测
要想触发JIT,首先需要识别出热点代码。目前主要的热点代码识别方式是热点探测(Hot Spot Detection),有以下两种:
1、基于采样的方式探测(Sample Based Hot Spot Detection) :周期性检测各个线程的栈顶,发现某个方法经常出险在栈顶,就认为是热点方法。好处就是简单,缺点就是无法精确确认一个方法的热度。容易受线程阻塞或别的原因干扰热点探测。
2、基于计数器的热点探测(Counter Based Hot Spot Detection)。采用这种方法的虚拟机会为每个方法,甚至是代码块建立计数器,统计方法的执行次数,某个方法超过阀值就认为是热点方法,触发JIT编译。
在HotSpot虚拟机中使用的是第二种——基于计数器的热点探测方法,因此它为每个方法准备了两个计数器:方法调用计数器和回边计数器。
方法计数器。顾名思义,就是记录一个方法被调用次数的计数器。
回边计数器。是记录方法中的for或者while的运行次数的计数器。
附录2: Java 语言简史
Java是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台的总称,最初推出的时候提出 “Write Once, Run Anywhere” 的理想愿景。
Java是一门面向对象编程语言,不仅吸收了C/C++语言的各种优点,还摒弃了C/C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。
Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点 。Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等 。
用 Java 实现的 HotJava 浏览器(支持Java applet)显示了 Java 的魅力:跨平台、动态的Web、Internet计算。从此,Java被广泛接受并推动了Web的迅速发展,常用的浏览器现在均支持Java Applet。
技术应用
安卓应用
金融业应用服务器程序
网站开发
嵌入式
大数据
高频交易空间
科学应用
Java版本历史
JDK 1.0(1996)
Sun公司发布Java1.0,发布初期叫Oak,后改名为Java(JDK1.0基本上只支持Java语言基础特性)
JDK 1.1(1997)
引入内部类
引入JDBC:是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。JDBC是面向关系型数据库的。
引入RMI:Java中一种特殊的类,可以将多个对象封装到一个对象(bean)中。特点是可序列化,提供无参构造器,提供getter方法和setter方法访问对象的属性。名称中的“Bean”是用于Java的可重用软件组件的惯用叫法。
引入JavaBeans:Java中一种特殊的类,可以将多个对象封装到一个对象(bean)中。特点是可序列化,提供无参构造器,提供getter方法和setter方法访问对象的属性。名称中的“Bean”是用于Java的可重用软件组件的惯用叫法。
支持反射能力
支持国际化和Unicode
J2SE 1.2(1998)
Java技术体系拆分为:J2SE、J2EE、J2ME
引入JIT:即时编译,又译及时编译、实时编译,动态编译的一种形式,是一种提高程序运行效率的方法。通常,程序有两种运行方式:静态编译与动态直译。静态编译的程序在执行前全部被翻译为机器码,而直译执行的则是一句一句边运行边翻译。
引入EJB技术
引入Swing图像化API
Java plug-in(Java Applet):Web环境下的小程序
引入集合框架
J2SE 1.3(2000)
初次引入 HotSpot VM
Java命名和目录接口(Java Naming and Directory Interface,缩写JNDI)包含在主程序库中(先前为扩展组件的形式)
用于实现动态代理的类
J2SE 1.4(2002)
语言上的改变:assert 关键字(断言)
正则表达式
异常链,允许一个异常来封装原先处于较低级别的异常
支持 Internet Protocol version 6(IPv6)
非阻塞I/O(NIO)
新增 日志API
J2SE 5.0(2004)
泛型:为集合提供编译期间 (静态) 类型安全,且不须为大多数类型转换 (类型转换) (规范在 JSR 14)
元数据(MetaData):也称作注解。让语言结构(像是类别和方法)能够用额外的数据标记,可以由元数据意识工具处理(规范在 JSR 175)
枚举
自动装箱拆箱:基本数据类型如int与Integer之间能够自动转换
静态导入(import static)
可变参数
JUC
For-Each 循环
Scanner 类别来解析来自各式各样的输入和缓冲
JavaSE 6(2006)
引入垃圾回收G1
优化锁与同步、垃圾收集、类加载等
@Override 接口
JavaSE 7(2011)
Sun被Oracle收购
钻石语法(泛型实例化类型自动推断)
try-with-resources语法糖
多个catch块用|连接
switch中可以使用字符串
支持动态语言
64位JDK的指针压缩
数值可加下划线
JavaSE 8(2014 LTS)
Lambda表达式(闭包,允许我们将函数当成参数传递给某个方法)
接口中的默认方法和静态方法
方法引用
无参构造器方法引用:类名::new 或者 Class::new
静态方法引用:Class::static_method (接受一个Class类型参数)
类成员方法引用:Class::method (没有参数)
实例成员方法引用:instance::method (接受一个instance对应类型的参数)
重复注解(同一个地方可以重复使用多次同一个注解,注解本身需要被@Repeatable修饰)
升级工具库实现
HashMap实现修改、ConCurrentHashMap实现修改
新增Stream API(java.util.stream)
新增Optional类以解决空指针问题
工具包,类依赖分析工具 jdeps
JVM方面:使用Metaspace(JEP122)代替方法区持久带(PermGen space)
JavaSE 9(2017)
JSR 376:在Jigsaw项目中将JDK模块化(参见Java平台模块系统条目)
JEP 222:jshell:Java Shell(一个 Java 交互式顶层构件)
JEP 295:AOT编译(通过 Graal VM 实现)[240]
JEP 268:XML Catalogs
JEP 266:更多的并发更新。包含响应式流的Java实现,及其部分替代品java.util.concurrent.Flow。
JEP 193:变量句柄:定义一个标准方法来调用java.util.concurrent.atomic和sun.misc.Unsafe操作的等价物。
JEP 282:jlink:Java链接器。该工具可以为模块生成一个包含了其所有依赖项的自定义运行时映像,同时允许生成一个包括运行它的JVM的可执行文件。
JavaDB被移出JDK
JEP 263:高DPI图像:自动缩放与尺寸自适应。
JavaSE 10 (2018.3)
JEP 286:局部变量类型推断 : var a = new ArrayList<>();
JEP 317:实验性的基于Java的JIT编译器。这是 Linux x64 下 Graal 动态编译器的集成。
JEP 310:应用程序类级别数据共享
JEP 322:基于时间的版本命名
JEP 307:适用于G1的多线程完全垃圾回收
JEP 304:垃圾回收器接口
JEP 314:更多的Unicode语言标签扩展
JEP 319:内置根证书
JEP 312:线程本地握手
JEP 316:在可选的内存设备上申请堆内存空间
JEP 313:删除本地代码头文件生成器javah
JEP 296:将所有JDK分支集成到同一个版本库中
JavaSE 11 (2018.9 LTS)
JEP 309:动态类文件常量
JEP 318:Epsilon:无操作垃圾收集器
JEP 323:lambda参数的局部变量语法
JEP 331:低开销堆分析
JEP 321:HTTP Client
JEP 332:支持 TLS 1.3
JEP 328:添加Java飞行记录器(JFR),其用于创建性能分析记录
JEP 333:添加ZGC(一个可扩展的低延迟垃圾收集器)
JavaFX、Java EE、CORBA 被移出 JDK
JEP 335:弃用 Nashorn JavaScript 引擎
JavaSE 12(2019.3)
JEP 189:Shenandoah:一个实验性的低延迟垃圾收集器
JEP 230:细粒度性能评审包
JEP 325:Switch 表达式(预览阶段)
JEP 334:JVM Constants API
JEP 340:仅保留一个 AArch64 平台的移植
JEP 341:默认类数据共享归档
JEP 344:针对G1,提供可中止的混合垃圾收集
JEP 346:针对G1,及时释放已申请但未使用的内存
.......
Java类库提升
附录3: James Gosling 历史采访
James Gosling on Java, May 1999
A Converstion with Java's Creator, James Gosling
by Bill Venners
June 15, 1999
First published in JavaWorld, June 1999
Summary
Java's Creator James Gosling talks with Bill Venners about the current state of the Java language.
On Wednesday, May 29, 1999 James Gosling, vice president and Sun fellow at Sun Microsystems and creator of the Java programming language, assessed the state of the Java language and platform in a phone interview with Bill Venners. In the course of the hour-long interview, Gosling discussed the current state of the Java programming language and the changes that are being considered for future versions of the language. Looking back to the Java language's early days, Gosling described the extent to which he had Jini technology in mind when he designed the Java language and the problems the Java platform solves in the enterprise. Gosling touched on those areas that have been a challenge for the Java language in the past and gave his impression of how they will be dealt with in the future.
The creator of the Java language also looked at how software and API development will change in the coming age of networked embedded devices. He explained why Jini technology's agree-on-interfaces approach to getting devices to work together on the network is superior to the traditional agree-on-protocols approach. In closing, Gosling shared his views about when it makes sense for developers to build a tool to solve the general case -- like he did when he invented the Java language -- and when it makes sense to concentrate on solving the specific problem at hand using available tools.
The Evolution of the Java Programming Language
Bill Venners: What has happened since the JavaOne show last spring that you think is significant in the evolution of the Java language?
James Gosling: The Java language itself has pretty much held constant. We've worked really hard to keep it very, very stable. We're being conservative about the Java language.
The kinds of things that have changed [since last year's JavaOne conference] have been implementations of the virtual machines underneath the language to give the language much higher performance, make it much more solid, and make it usable in many more situations. On top of the language we've done a lot of work with APIs. One of the key features of the language is this ability to define new facilities as classes. That's been where the explosion has really been: in all the APIs on top of the Java language itself. One main motivation for being conservative about the Java language and keeping it stable is so that all of this work on APIs that are on top of it doesn't get disturbed. Because that's where the real value is, in the stuff that's on top.
Bill Venners: What kind of changes can we expect to see in the language in the future?
James Gosling: There's a list of things that have been on the table for quite a long time. One of the things we get asked about a lot is type polymorphism, which shows up in C++ as its template maker. Five years ago, when I was trying to figure out the right thing to do as far as developing a new language, there were probably twice as many type polymorphism systems in the world as there were experts in type polymorphism. And nobody thought that anybody else's solution made any sense.
While there was a general feeling that there was something good about type polymorphism, exactly what it should look like was very unclear. There's been a really heated debate on this subject over the last few years. (There's a guy here named Gilad Bracha who's run herd on that debate, and a mailing list on the subject called the Java Genericity mailing list.) At this point we're down to about three proposals for type polymorphism, and it looks like we'll get to some kind of a resolution.
If you go to http://java.sun.com/people/jag/Presentations/COOTS99/index.html, you'll find a set of slides from a talk I gave in San Diego four weeks ago at COOTS 99, the Conference on Object-Oriented Technologies and Systems. In this talk, I go through unanswered questions concerning the Java language, including talking about what changes people have been asking for.
The number one thing people have been asking for is an assertion mechanism. Of course, that [request] is all over the map: There are people who just want a compile-time switch. There are people who think those are the spawn of the devil, and they want something that's more analyzable. Then there are people who want a full-blown Eiffel kind of thing. We're probably going to start up a study group on the Java platform community process. We've been using that process for everything, including language changes. There's already a study group starting up on type polymorphism, and a study group is also probably going to start up on assertions.
Performance and the Java Language
Bill Venners: Now that the Java HotSpot performance engine is released, to what extent is performance solved? Are there areas in which performance still can be improved? What future plans might you have for performance improvements?
James Gosling: Performance is one of those things that you're never done with. There is no system on the planet that is ever finished with performance. But our performance is getting pretty good. Lots of people do benchmarks of server applications, and compared to C and C++, we're basically right in the same ball park.
There is room for performance improvement in the new 2D graphics libraries in the Java 2 platform; these certainly need some tuning. One of the persistent performance problems we've had that has been pretty hard to grapple with involves the demand for features: people keep asking us to put this in and put that in. Look at "Project Swing," for example. "Project Swing" is this UI toolkit that is industrial-strength. It's got everything in there, and that makes it kind of big. And big always turns into a performance problem. So we're working on ways to try to make "Project Swing" faster, trim it down, and give it fewer interdependencies, so that it is fast and nimble.
It's this difficult paradox -- that the more there is, the more there is. In terms of the Java HotSpot performance engine, we've put out the first release of it, but there are more interesting optimization techniques that we would like to try which are not there yet. There are many more tricks in that particular bag, and there's a lot of room for it to grow.
Bill Venners: Can you be more specific?
James Gosling: One of the things that made HotSpot rather difficult is that it's a collection from some fairly large number of PhD theses -- a long esoteric list of dynamic compilation tricks. There were a bunch of things that have an awful lot of value that we decided not to do just to get Hotspot out there.
We do an awful lot of dynamic compilation tricks in the Java HotSpot performance technology now, but there's room to add more. Right now [performance-wise] we are as good as C or C++, often beating them, and it's pretty clear that we can get greater improvement out of it.
Another thing is that when you talk about optimizing something, it's often optimizing with respect to a particular situation. The current Java HotSpot technology release is targeted toward making server applications really fast. The kinds of tuning you do in server applications tend to be different than what you do in other places.
Inspiration for the Interface
Bill Venners: In Java you included multiple inheritance of interface, but left out multiple inheritance of implementation. Were you trying to say anything to designers by making the interface a separate construct? Were you trying to say anything by leaving out multiple inheritance of implementation? How did that come about?
James Gosling: It listened to people from the C++ and Objective-C camps, and I tried to sort out who had the most happy experiences. The Objective-C notion of a pure interface with no implementation seemed to have worked out really well for people. It avoids a lot of the sticky issues such as disambiguation that people get into in C++. It's still kind of messy. It's an area that I don't feel totally happy with.
Bill Venners: In what way?
James Gosling: Another way for doing these things is a technique called delegation. Some ideas in the delegation camp felt good, but I never came up with anything that really worked. I ended up with the interface construct, which felt simple enough to be comprehensible, sophisticated enough to be useful. It also avoided any of the tar pits that the other folks got into.
The Jini Vision
Bill Venners: I heard Java was originally envisioned for embedded devices. To what extent was Java designed with what would eventually come to be called Jini technology in mind? In other words, were you just thinking about embedded devices, or were you thinking about a Jini technology-like world?
James Gosling: Oddly enough, something very much like the Jini technology world was in there from day one. The very early version of the Java language, which was called Oak and ran on the Star Sevens, had a distributed message system in it that was very much like RMI. In fact, even though the original distributed message system got ripped apart when we started doing some of the cable television stuff, there was enough of it still lying around that when the RMI folks went to do RMI, they were able to fit in some of it.
Jini's Footprint
Bill Venners: What is the JDK footprint for Jini technology-enabled devices, and is that going to be a problem for people who are making devices where every tenth of a penny counts toward cost savings?
James Gosling: The Jini technology team has put a lot of effort into making it so that it can handle really teeny devices. To be technology-enabled, a Jini technology device doesn't actually have to have a full-blown Java virtual machine in it. All it has to be able to do is respond to messages over the network. And it has to be able to do a certain amount to identify itself and read class files out of ROM.
Homogeneous Execution Environments
Bill Venners: For mobile code to work, the Java platform needs to provide a homogenous execution environment, no matter where you go. That's been difficult to achieve for applets landing in just a few browsers. Is there something new that's going to help Jini service code see a more homogenous Java platform wherever it goes in all these different kinds of devices?
James Gosling: We really have had very limited problems with homogeneity for people who do tested VMs. The browsers turned into a real serious problem. There was Microsoft on the one hand that was just being evil. And then there was Netscape that ran into all kinds of engineering and financial difficulties. So the Java embedded in browsers was just turning into an unfortunate situation for us.
Bill Venners: But basically Sun developed a bunch of tests, and VM and API implementations that actually go through the tests are more homogeneous?
James Gosling: That story is quite different, certainly, for people who take pieces of Java technology-based code and squirt them around between servers and out to Oracle and the rest.
Bill Venners: Do you envision a solution to the browser problem?
James Gosling: We have a solution in place for Netscape 5.0, which hasn't been released yet. The general structure of the solution we're pursuing, that we like the best, is the Java Plug-in, which has been working out pretty well. What we need to do is make that more robust, deal with some delivery issues, and get it tied into the browsers better. But the basic direction for dealing with the browsers is taking the [Java] Plug-in product and making it industrial-strength.
Picking and Choosing APIs
Bill Venners: People who do embedded devices always seem to have this pressure to make things fit, which gives them the need to pick and choose which APIs they'll support. Is there some way of dealing with this pressure, such as somehow getting them to all have the same set of APIs?
James Gosling: Trying to get them to have the same APIs is why we came up with these API subsets. Some of that has worked, some of it hasn't. Much of what we've been trying to do lately has been to make it so these folks can do dynamic loading of pieces of the APIs that they don't support.
A certain amount of it has been trying to get people in the different industrial segments to get together and agree on what the common things are. But what should the standard APIs be that are available in a toaster? Or in some robot arm controller? They're very different.
Bill Venners: So what about the subsets, like Embedded Java and Personal Java? What's the status of those things then? It sounds like you've recognized that maybe you need to go into each little niche and help those people get together and figure out what APIs they need.
James Gosling: We figured that it was pretty much hopeless for us -- both hopeless and sort of arrogantly presumptuous -- to go into the different industrial segments and tell them what we think the API should be. For example, this is what we think the API should be for the GPS navigation system; this is what the API should be for telescope control; and so on. Those aren't things that we have any expertise in.
[What] we really have an interest in is making sure that the participants in those industries get together and figure it out. One of the things we try to do is facilitate matters where we can. So we might have a person or two who's involved in these efforts, but we certainly don't try to control them or drive them or run them.
How Software Development Will Change
Bill Venners: How will the emerging hardware environment of network-connected embedded devices change the way software and APIs are developed?
James Gosling: I think the biggest difference is that you can't just sit alone in a room and build stuff, because the things you're building interact with everything out there. You can't just sit alone and do whatever you want.
Bill Venners: And why is that?
James Gosling: Because you're trying to interact with other things, you have to know what the other things do. If there are multiple people doing similar kinds of things, they have to have some kind of an agreement on how these things should work. If you're designing an electrical power delivery mechanism, for example, you have to design a wall socket. And everybody has to use the same wall socket; otherwise those toasters won't be able to plug in to you.
It becomes an environment where people have to be much more socially involved. It really is a community thing.
The Idea Behind the Interface
Bill Venners: You once said that the core of object-oriented design is "figuring out what the interfaces are." Could you elaborate on that?
James Gosling: The interfaces are the things that connect the pieces. You've got a toaster and a power plug in the wall; it's the way you connect. The core of the object-oriented design thing is to try to figure out what the interfaces should be. The actual technology of object-oriented design in a programming language is how you express those interfaces.
From a developer's point of view, the art is in figuring out the important things to have in the interface. Actually, the hardest part is figuring out the things you should leave out. Because one of the important aspects to designing interfaces is to make them say just enough so that people who want to use them can use them and do what they need to do -- but not so much that it makes it difficult for people to change things.
Interfaces vs Protocols
Bill Venners: Microsoft claims their Universal Plug and Play (UPnP) is superior to Jini because it uses the time-tested approach of having people come together and define protocols. At the Jini Community Summit last week, Bill Joy said that he's seen how long it takes people to come to agreement on protocols. And he thinks it's easier and faster to agree at the higher level of an interface. Could you compare the two approaches? In particular, why is Jini's agreeing on interfaces approach better than UPnP's a greeing on protocols approach?
James Gosling: The big deal to me is the flexibility that Jini technology gives you. If you look at the phone companies, they offer special features -- like call waiting. It turns out that these special features in the phone system are dependent on all the different switches and components in the infrastructure being built to support particular protocols. So if you want to invent some new thing, as in call waiting, the only way you can get it out there is to go around to everybody and convince them to implement this new protocol. Then, everybody must upgrade every piece of hardware in the entire infrastructure.
The Jini technology story is that up-front you agree on a mechanism for building flexible systems. That allows new behavior to be downloaded into systems. When people invent new things, they don't have to go around convincing people to handle these different protocols. There's a standardized way for people to offer some new behavior for you. And then within the context of security policies, the behavior just sort of gets involved.
One of the reasons that is particularly important is that for standardized protocols that everybody wants, it's possible to get them through the process, even though it's really, really painful . But for specialized things, it just never happens.
Bill Venners: Because of politics?
James Gosling: Yes, because once you've got the standardized protocols, if you want to add some specialized thing, you'll never do it.
Bill Venners: When you say "building in flexibility up-front," are you talking about Jini being able to send the object?
James Gosling: The key thing about an object is that an object is data plus behavior. So when Bill Joy talks about downloading an object, he's talking about downloading behavior as well. When you've got a hand-held remote control and it's talking to some things in your AV system, if you have a standardized protocol, then if somebody invented a new kind of filter function or kind of box, you can't get to it from your remote. Go home and look at the universal remote controls. When DVD players came out, none of the control systems dealt with DVD players. Nobody's home stereos had a connector in the back for a DVD player. And so the whole standardized protocol thing totally failed. And it turns into a real block on innovation.
With something like a hand-held remote control, where the remote control has an LCD screen, the control software gets downloaded to it. If somebody has a DVD player, all it does is, it takes the object that represents its interface and sends it to the remote control. And that interface object can do whatever it wants on the screen, whatever is appropriate for that newly invented device.
Jini technology handles the control parts of the system, but you also need the interconnection part. In the audiovisual world, there's a thing called IEEE1394, sometimes referred to as FireWire. It started out at Apple, and it's now being pretty heavily pushed by Sony. It's a 400 Mbps networking standard for home audiovisual equipment that lets you shift audio and video and control stuff across networks. You put all those pieces together, and you end up with a system that can be incredibly flexible, where people can invent new things that just fit in.
Server vs Service
Bill Venners: Could you elaborate on the distinction between a service and a server?
James Gosling: It's like the difference between an interface and an implementation. When people talk about a naming service, it's -- in the Java world -- an object with an interface that you talk to and say: Here's a name, look it up for me. And whether that turns into pulling something out of a hashtable locally, or sending a network request to a Novell server, or a Sun server, or whatever, is independent of the service interface. It's actually a bad thing for the application developer to know how that request is being satisfied. If you just ask to look up a name and then it gets done somehow or another, it gives you hugely more flexibility in deciding what's where.
The Jini technology folks push this really hard because in the case of a name server, they need to be able to handle some pretty dramatic scaling. They need to be able to have very small name servers that handle two or three devices. And they also need to be able to handle large enterprises with hundreds of thousands of nodes. If you try to span that with one particular technology, you'll just get into trouble. Because there are name-server technologies that work really well at the high end of the scale that are just way too heavyweight at the low end of the scale, and ones that work just fine at the low end of the scale that just run out of steam at the high end.
So, the way you do scaling is you step back from any particular implementation, abstract from what the service is, and then as you run up and down the scaling chart, you switch from one implementation to another.
Bill Venners: And why is it a bad thing for application developers to know about how something's being implemented?
James Gosling: Because as soon as they do that, they get committed to one particular implementation or the other and then all of a sudden the repluggability of different servers becomes more difficult.
The Enterprise Vision
Bill Venners: To what extent did you envision the Java language playing a role in the enterprise when you first developed it?
James Gosling: Not at all. It was a funny thing where very early on the view was that there was this established technology base that was pretty much impenetrable. Even though there were problems, market forces meant it was essentially impossible to break into the enterprise. So we decided to focus on areas where things weren't as tied up, which is partly where the consumer-electronics thing came in. We focused on that area because it seemed to be the most open one.
But when I designed the whole Java technology system, it came with years of experience doing all kinds of systems. And the reaction of enterprise folks, when they looked at the Java technology system, was, "Wow, this solves a whole bunch of my problems!" But early on getting into the enterprise certainly wasn't a goal.
Bill Venners: So given that it was more perceived along the lines of embedded devices, or that's how you thought of it, would you say there's deficiencies in Java for the Enterprise environment, or areas where you could do better at the language level?
James Gosling: I guess I've done these embedded languages for a very long time. And one of the lessons that kept getting beaten into me over and over again is that when you design a system, you have some kind of a model of what people are going to do with it. And so you tend to build for that model. But every time I've done that, it's just been miserable, because people have always taken the system and done things that I never, ever expected. So when I designed the Java language, in many ways it was grotesquely overdesigned for its target.
Bill Venners: As a result of learning the hard way that people like to use things in ways you never imagined?
James Gosling: People always want to scale them up in amazing ways. And so I decided that this time around, rather than trying to focus on the particular application area, I was going to do a full-blown general-purpose thing.
Java Language Development in the Enterprise
Bill Venners: How well does Java technology scale to, say, one hundred developers in single enterprise who are all banging out code?
James Gosling: It actually scales pretty well. There are a number of things that make that work. The central thing is the whole object-oriented philosophy, this business of building systems out of modular parts. And the modularity of systems in the Java language is taken very seriously compared to other systems. You really can't build a nonmodular system in the Java language. The interfaces between modules are very strict -- you can't get around them. They're really like a contract.
So the different parties have a really clear understanding of what each is responsible for. This helps teams work together because there's a clear understanding of what the rules and responsibilities are of team members. And as each individual team member knows what he or she is doing, you don't get this problem where people have their fingers in code all over the place.
Enterprise Problems Solved by Java Technology
Bill Venners: You said you designed Java in a general way and then people on the Enterprise arena came along and said this solves a lot of my problems. What kind of problems does the Java language solve for the enterprise?
James Gosling: It's a long list. I think probably the biggest ones are a lot like the stuff I've been talking about: the modularity, making things so that you can do modules that really work properly. In C++, there's been this problem that's often been called the fragile base class problem: If somebody defines a class and somebody else does a subclass, when the first person changes the base class, you have to recompile the subclass.
Also, in the Java language there's nothing you can do to cause memory to get corrupted. There are years and years of statistics on where the energy goes in maintaining large pieces of software. And, historically, over 50 percent of the hours that people have spent tracking down bugs have turned out to be due to some flavor of memory corruption. With the way that pointers and arrays are in the Java language, essentially all of those go away.
Bill Venners: It sounds like the Java programming language addresses a lot of productivity issues, then, for the enterprise.
James Gosling: Yes, and productivity is not just the productivity of developers; it's also the reliability of the thing they produce. Reliability and productivity are linked. Because the less time you spend debugging something, the less often something crashes when it's out there in the field, and the more productive your developers are.
To Tool or Not To Tool
Bill Venners: I heard that when you went off to the Green project, you started writing the software in C++, and then you later decided to make a new language. There are times when I've felt the urge to develop a tool to solve a problem as opposed to solving the problem itself. Could you say a few words about when it makes sense for developers to develop a tool to solve a general case, as opposed to solving the specific problem in front of them?
James Gosling: That's a deeply unknowable question, because it's not like there's some little scientific formula that sort of says: If you're feeling more than 27 ounces of pain, then build a tool. It's really easy to get started off in this path of building tools, and then you never actually do the thing you set out to do; you just build tools.
In a sick sense, that's basically the story of my whole career. I set out to do things, and I always end up building the tools. And then the actual thing kind of gets lost. And there's no real answer other than having been there many times and getting kind of a feeling.
Tools in general make sense when there are repetitive things that they can help you with. Programming languages are a really dubious thing to create. I've done a lot of them, and they can be really good solutions to all kinds of problems. But they come with a learning curve infrastructure problem that can make them pretty difficult. And, actually, in the Green project I wasn't real happy about going off and doing a new language. It started out with me not trying to do a new language, but trying to fix some underlying issues in C++ that were not so much C++ the language, but C++ the compiler.
The Java programming language has things about architecture-neutral executions, for instance, and dealing with the fragile base-class problem. You can actually solve those problems within the context of C++. I mean, it's just sort of an artifact of the way the C++ compilers are built that they have this problem. My original goal was to build a C++ compiler that didn't have these problems. But then as I worked on that, and as the developers on the project sort of came after me, it became really clear that there were other problems that needed solving, and it sort of evolved into just a new language.
This article was first published under the name James Gosling looks back at the Java language's past and forward to its future in JavaWorld, a division of Web Publishing, Inc., June 1999.
Talk back!
Have an opinion? Be the first to post a comment about this article.
About the author
Bill Venners has been writing software professionally for 14 years. Based in Silicon Valley, he provides software consulting and training services and maintains a Web site for Java and Jini developers, artima.com. He is author of the book: Inside the Java Virtual Machine, published by McGraw-Hill.
James Gosling on Java, May 2000
A Conversation with Java's Creator, James Gosling
by Bill Venners
June 15, 2000
First published in JavaWorld, June 2000
Summary
Java's Creator James Gosling talks with Bill Venners about the many Java-related topics.
On May 31, 2000, Bill Venners rode his bicycle up to Sun Labs in Mountain View, Calif., and spoke with James Gosling, the inventor of Java and a vice president and fellow at Sun Microsystems. In this interview, Gosling talks about his current interest in developer tools, his recent work on the realtime JVM, the practicality of mobile objects, the importance of strict interfaces, the reasons package access is default, and the robotic light bulbs at a Doobie Brothers concert.
Current Projects
Bill Venners: What have you been working on recently here at Sun Labs?
James Gosling: These days, I'm putting together a group to work on developer tools based on work done by the NetBeans folks, who put together this really nice framework for building tools.
One of the things I'm trying to do is to build a set of tools that professional developers would use. Typically, tool vendors tend to go after the mass-market developer, and I guess I'm not one of them, so they generally don't interest me. And, by and large, all the tool developers have kind of ignored the higher-end developers. So I'm spending some time thinking about that.
But, in actual fact, I've spent most of the last year working on the realtime spec for Java. That's really what's occupied me for most of the last year. I was doing that pretty much full-time until three or four weeks ago, when we finally got a camera-ready copy of the book off to Addison-Wesley.
Bill Venners: Which book?
James Gosling: The realtime specification for Java. It's a spec that was done under the Java Community Process.
The Realtime Specification for Java
Bill Venners: Could you give an overview of what's in that spec and what it's all about?
James Gosling: The realtime spec for Java is all about how you write programs in Java on realtime systems. And there are a number of components to it -- simple things like dealing with accurate dates, scheduling events. Most of the hard things have to do with deterministic timing.
In the realtime world, what people care about is performance, to a certain extent. But more important than performance is, generally, determinism.
When you say, "I want this to be executed at that time," in general, by God, you mean it. And then it's not allowed to slip. And that has effects in two areas. One is scheduling, and there's all kinds of exotic scheduling algorithms that can be in there, and the realtime spec has a general framework for putting in all kinds of schedulers.
The other side of it is that there's one big source of non-determinism in timing in Java right now, and that's garbage collection. And garbage collection is really the number one hard problem.
On the one hand, people look at garbage collection and what it gives you, and they by and large really like it. Particularly folks in the realtime world like garbage collection a lot because it's tremendously useful for increasing the reliability of systems and speeding up development time. It just helps to hold the whole robustness story tremendously.
Bill Venners: You said particularly the realtime people like that.
James Gosling: Yeah. Well, because they tend to be even more worried about systems that crash. With a lot of these realtime systems, if the software crashes, an actual person dies. It's a control system for an airplane or a robot arm -- you're just getting ready to stop the arm and you garbage collect and the arm just keeps going because nobody's telling it to stop. And it takes out a wall or innocent passers-by or something. And so you can't tolerate that kind of thing.
And so there was a general consensus that we wanted to have garbage collection in there but we didn't want to live with the hiccups that you get when your average garbage collector kicks in. All garbage collectors have the effect that they tend to shut down the system for some interval of time. And some of them you can actually tune the interval.
So, like in HotSpot, there's a limited amount of control that's possible over how long each GC step takes. But if you're writing an application whose timeliness needs to be tighter than what something like the HotSpot VM can do, then you're in trouble.
One of the things that we decided fairly early on was that an easy out on this problem would be to, say, only use "realtime garbage collectors." That's garbage collectors that have essentially zero pause time because they either back out or are doing things truly in parallel.
A couple of people in the group did a literature survey and they concluded that real realtime garbage collectors essentially didn't exist. There were a lot of things which were claiming to be realtime garbage collectors that were close but not good enough. And the usual extent of closeness was that the people were saying, "Well, we're realtime because we never pause more than a millisecond." Or, "We're realtime because only one chance in a billion will we ever actually back off and do a full mark-and-sweep."
Unfortunately, both of those invalidate the GC algorithm in some applications. In the realtime world, people are worried about the worst case. They don't care at all about the average case or the best case, they care about the worst case. And if the worst case is that this algorithm will actually do a full mark-and-sweep -- shut the thing down for seconds -- then it doesn't work, even if it happens once in 10 or 15 days of running. If the thing that's running is the thing that's controlling the flutter of the wingtip of an F-16, after 10 days the airplane turns into dust. And that doesn't work.
For GC algorithms that have fairly small minimum times, often people will claim that they have a realtime algorithm, and then they'll say it's got a maximum pause time of a millisecond. And that works for some applications and doesn't for others. One way to characterize realtime algorithms is based on the maximum latency that they can tolerate. And some of them can live just fine with a millisecond; some need something much finer than that.
So what we ended up doing was defining a way to allow a special kind of thread to run even while the garbage collector is running. And if you know much about garbage collectors then you think about what is it that has to be true about a thread if it's going to run while the garbage collector is running. You end up with a fairly onerous set of restrictions. Namely that whatever the thread does, it does not allow it to touch an object in the garbage collector heap, and it's not allowed to move a pointer to one of these objects around.
And so we've defined two subclasses of thread, one called the realtime thread, which is a thread that has all kinds of extra scheduling parameters besides just the priority. And then there's another subclass of that called the no-heap realtime thread, which is one that also has the ability to run while the garbage collector is running. But those threads are not allowed to access heap memory. And the way that they are able to work is that there's a way to allocate what are called "immortal objects." An immortal object is one that is allocated -- it stays there forever and it never, ever goes away.
The immortal objects correspond pretty much to what people actually do as standard practice in realtime coding today. Generally when people are doing serious realtime work they pre-allocate everything. And then they sort of go into their realtime reading windows with the things which realtime never, ever allocates. Because it turns out that almost all the allocators in the world actually have non-deterministic timing.
See, almost everybody's malloc() or free routine has non-deterministic timing. And so in general, people don't use them for the intense realtime application. So the whole no-heap thing/immortal objects, if you describe that to an average Java programmer, they'd say, "Oh my God, this is really awful." But if you describe it to somebody who's been doing realtime programming, their reaction is sort of, "Gee, that's what I do today. It's not a big problem."
But it gives them the advantage of this universe where people doing these really time-critical things can actually interact with the other world that is done in Java, and get all the advantages of writing programs in Java, and also get all the portability stuff. That's really the most important piece.
Bill Venners: How do the new scheduling capabilities work?
James Gosling: With scheduling, there are some new objects introduced and one is called the scheduler. And a scheduler determines when threads should get started up. And one of the parameters of the scheduler is if it's a no-heap thread, it can then start while the garbage collector is running.
But normally, the scheduler is similar to what happened in typical thread scheduler. It's looking at the queues of threads that are available to be one. They picked one, and in most everyday computer systems these fairly simple priority-based schemes work pretty well.
In realtime systems, generally you've got a notion of a deadline when this particular computation has to be done. And so there are ways to associate properties with threads like what its deadline is, what the expected amount of work is. And that gives a scheduler more information to sort of trade off which things to run now.
It's an open-ended framework, so that people can invent new schedulers and plug them in. There's also hooks in there for doing what people in the realtime world call feasibility analysis. Namely, you've got a set of threads, and you ask the question, "So does this make any sense?" If you've got three or four threads, each of which wants 100 percent of the CPU all the time, it makes no sense at all because you'd need three or four CPUs. Or three or four times as much CPU as you've got.
So you can do things like back out or not start systems, or go into some sort of fail-safe mode.
Bill Venners: What do you mean by "back out"?
James Gosling: Like not start the system. It's application dependent. When the feasibility analysis fails, what do you do?
Bill Venners: So the VM does the feasibility analysis before it starts? Or does the application do it?
James Gosling: The application effectively is in charge of invoking it. Because what the application does is it sets up a set of threads. And then it asks the scheduler "Is this feasible?" And if it is, then the system carries on. If it's not, then the application decides what to do. And it may do things like decide to cut back on its workload somehow. Or it may just even refuse to start.
It's sort of like having the "on" button on your airplane, if it turns it on and says, "Sorry, install a new CPU."
Bill Venners: Is this going to be incorporated into all future VMs? Or will there be realtime VMs and a not-necessarily-realtime VMs?
James Gosling: Yeah, it really ends up being two. There's the Java VM and then there's sort of a specialized class of Java VMs which would be the realtime Java VMs.
Bill Venners: So there are certain kinds of applications then that would run on realtime VMs that just wouldn't work on regular VMs?
James Gosling: Correct. The standard VM is not optimizing for the realtime performance. In general, what non-realtime systems are optimizing for is not timeliness but throughput. So you're trying to see how much raw performance you can get out of the whole system. And whether you're hitting your deadlines on a millisecond by millisecond basis isn't really relevant.
The Practicality of Mobile Objects
Bill Venners: Why don't we switch gears and talk a bit about mobile code. I've had a few concerns about the practicality of sending objects across the network, and I would be curious to hear what your thoughts are. Let's start with finalization.
One of the issues that has come up in Jini discussions is cleaning up after mobile objects. If I'm a client and I receive a mobile Jini service object, that object can consume my local resources by firing off a thread, opening a socket, and so on.
From a Jini lookup service, I can grab service objects about whose interface I have absolutely no prior knowledge. I can grab them by name. I can use the browser methods to find things that look interesting and grab them. If I have prior knowledge of the interface of the object, then there's probably a cleanup method that I'm supposed to call when I'm done with it. If the object is nice, it will relinquish all of my resources that it consumed when I invoke the cleanup method.
James Gosling: Right.
Bill Venners: But first of all, it may not be nice. And second of all, I may not have any prior knowledge of that interface. So how do we make sure that clients don't always run out of resources when they're using mobile code?
James Gosling: There are several answers to that. One is when you stop referencing that object, it goes away. And things that it refers to go away. And the finalizer will get called.
In other words, that it's actually pretty rare to bring in some mobile object, not have some idea what interface it implements. Generally, these pieces of mobile code are used in things like editor plug-ins or database plug-ins, and they tend to do a Class.forName() or some sort of look-up that gives you this new Class object. And you do a newInstance() on it. And then you say, well gee, are you a plug-in for this area? Are you a device manager? Or are you a printer device manager? Then you can start talking to it.
If you have absolutely no idea what you're expecting, just take an arbitrary object in, there's not a whole lot you can do with it other than say, "Hey, isn't this nice?" And almost always, people do have standardized interfaces for these things.
And if you're designing one of these standardized interfaces and having the imported stuff go through some active and passive phases where you're getting rid of, dumping resources and that, then defining a method to clean things up is a good thing to do.
Bill Venners: There's also denial-of-service attacks or bugs where even if you do call the cleanup method, if the method forgets to kill a thread, that thread doesn't go away.
James Gosling: Sure. Denial-of-service attacks are generic and are really hard to deal with. And unfortunately, they're hard to deal with in a relatively deep sense. You can throw some signal at a thread. The stop() methods are there. They're deprecated. The manual says, "Don't use this. Bad things will happen." But they are there, right? And so you can stop a thread.
And all the VMs I know of, stop() actually does work. And unfortunately it does have some side effects, it has some consequences. But it's like the consequences that exist in any other system when you try to forcibly shut down something without giving it a chance to clean up. It certainly happens with Unix processes, with threads, anybody. C library, if you just shoot a bullet into its head, it doesn't clean up.
And if there were things that needed cleaning up, like reconstructing some data structure, like this thing representing a filesystem that's linked into some linked list, you could leave that kind of broken.
It absolutely happens with everybody's systems. Whether it's C threads or Unix processes, you have exactly the same problems. It's essentially impossible to stop a process and guarantee that it will be clean, that it will be graceful. All the deprecation of stop says is you can't guarantee that it's graceful.
And it's not any different than what happens with stop in any other system. It's just that we decided that it was important to spell out to people that this is a dangerous thing to do, and what you really ought to do is do something more graceful.
Where you really get into trouble is where people start using things like stop as a standard way of shutting down a thread. And really, the right way to do it is you have some application-specific way of doing it. The cleanest ways are, generally, if you've got like a thread that's in a loop, doing something, then you put a global variable in there that says, "I want it shut down." Have the thread actually testing it. And then at a point when everything is clean, you exit the loop.
Then, if you have your own cleanup method, you call a cleanup method. And unfortunately, graceful shutdowns, because they are dependent on exactly what the semantics of the operation are, they're intrinsically application-dependent.
So the right thing to do is to do the layered approach to shutting down some thread or some object. Namely, you tried to do it gracefully. If a graceful shutdown doesn't work, then depending on the situation you either pull out a gun and you either shoot that thread, or you shoot the entire system.
Bill Venners: I thought you were going to say shoot the programmer who sent you that code.
James Gosling: Well, right. You kind of pick up your pistol and you decide where to aim it at.
The Importance of Strict Interfaces
Bill Venners: Another concern I had about Jini was testing, because the trend is over time, everything will become network-connected embedded devices. And we'll want all those devices to work together. In a world where everything is connected to everything, Jini kind of offers a way for things to work together at that level of interfaces instead of protocols.
The concern I have is that let's say I have a blender. I want my blender to work with all the clients that know about the well-known blender interface. I can't test my blender with all the clients, because there are too many of them, and I don't know what they are, and a lot of them don't exist yet. My service object is going to fly into these clients and is supposed to work with them.
So what has to happen is we have to agree on these semantics, the APIs.
James Gosling: Right. The API is a contract. And by God, you better follow it. And by God, you better write it down because your point about some of these clients haven't been invented yet, that's absolutely true. And that's the way you really want the universe to be. That you can define a blender that's going to be controlled by or interface to things that haven't even been invented yet.
Because if you have a universe where in order to work, you have to test that blender against everything that interfaces to it, then you do that testing, and then never again can anybody invent something that interfaces to a blender.
And that's kind of a way that things like Windows ended up getting stopped. And a lot of that has to do with things like, what is the API to Windows? And the answer is, nobody knows. In fact, even Microsoft doesn't know what the Windows API is. Because they publish an API, but lots of people sneak in through back doors. And so you go to any bookstore and you can find these books: "Undocumented Windows Secrets."
And those books are usually of the form, "If you get this handle back from so and so, then you cast it to an integer and you add 13, you'll find in bit three something that tells you this." Right? And of course the people who built the system, yeah, they might have that bit there, but that is a part of their internal implementation. They have no idea that people on the outside were using this.
So they know what pieces of the interface they specify to people on the outside. But because there isn't a really good, strong interface notion in C, people just sort of reach in through the back doors. And they do God knows what. And so when Microsoft goes to release a new version of Windows, what they essentially have to do is test everything. They take, I don't know how many thousands of applications that they run it against, they run them against Windows. And some of the ones that are the worst in terms of running through the back doors are the games.
The games seem to be just completely savage about doing whatever it takes to find whatever display chip you've got. Tweaking with the guts of the chips registers in parallel with the device driver. And that's kind of standard practice in the gaming world.
Bill Venners: They probably see themselves as programming the hardware.
James Gosling: Yeah, it gives them that performance, but holy mackerel, does it make life hard.
Bill Venners: What you're saying is because these APIs would be Java, they're object-oriented, you can make the implementation inaccessible to people from the outside. So they can't get that integer and tweak -- add 13 and tweak this bit, because it's part of the implementation.
James Gosling: Right. It was a very important property of interfaces that they are very strict. That wasn't just me deciding to be nasty. That was: the world is madness if the contracts aren't strict. Because then all of a sudden -- the whole notion of object-oriented programming falls apart if the interfaces aren't strict.
Because then all of a sudden you lose the ability to unplug this and plug that in. Because if you don't know what the shape of the plug is, how do you know it can plug in? And whether plugging in on this side or plugging in on that side, you just don't know.
The Semantics of Interfaces
Bill Venners: I still have a question, though, about semantics. First of all, Java will keep implementation accessible to the client side -- let's say a Jini service or whatever. But I still have to understand that spec, which is written in a human language, and the JavaDoc comments that were also written in a human language. And people interpret human language descriptions differently.
James Gosling: Absolutely. The whole issue of doing semantic specifications is actually very hard. Lots of people have taken many runs at it. You've got languages like Eiffel, which have pre-conditions and post-conditions in that. And that gives you a piece of it. And you can do some of that by hand in Java, and actually the assertion facility is intended to be a part of that.
In terms of going far enough that you could actually not have an English specification, but only have essentially a machine-understandable specification that forms a contract, that's been a Holy Grail for generations of mathematicians. And the answer ends up being essentially that it's been pretty much a failure. Because the specifications are themselves a source of error.
Bill Venners: You mean the specification in the formal language?
James Gosling: Right. When you go from a language to some other language -- whether it's a formal language, some sort of mathematical language -- you still have the same problems. Namely that the formal specification may itself be ambiguous. It might not have occurred to the guy who wrote it down that thus and such a problem could be there. And so you get exactly the same problems. And on average, while formal specifications help, they don't solve the problem. They just move it around.
Java's Access Modifiers
Bill Venners:Java has four access levels. The default is package. I have always wondered if making package access default was convenient because the three keywords that people from C++ already knew about were private, protected, and public. Or if you had some particular reason that you felt package access should be the default.
James Gosling: A package is generally a set of things that are kind of written together. So generically I could have done one of two things. One was force you always to put in a keyword that gives you the domain. Or I could have had a default value. And then the question is, what makes a sensible default? And I tend to go for what is the least dangerous thing.
So public would have been a really bad thing to make the default. Private would probably have been a bad thing to make a default, if only because people actually don't write private methods that often. And same thing with protected. And in looking at a bunch of code that I had, I decided that the most common thing that was reasonably safe was in the package. And C++ didn't have a keyword for that, because they didn't have a notion of packages.
But I liked it rather than the friends notion, because with friends you kind of have to enumerate who all of your friends are, and so if you add a new class to a package, then you generally end up having to go to all of the classes in that package and update their friends, which I had always found to be a complete pain in the butt.
But the friends list itself causes sort of a versioning problem. And so there was this notion of a friendly class. And the nice thing that I was making that the default -- I'll solve the problem so what should the keyword be?
For a while there actually was a friendly keyword. But because all the others start with "P," it was "phriendly" with a "PH." But that was only in there for maybe a day.
Bill Venners: Well, I think one consequence of having package access be the default is that a lot of data ends up package access. I myself like to make data private, but I sometimes forget to type "private" so the data ends up package access.
James Gosling: Yeah, and it sort of gets into another thing -- one of the things that I had wanted to do early on was formalize setting and getting something in the language. You know how in JavaBeans there's this sort of convention that you write setter and getter methods? But I did a bunch of surveys of developers at the time, about whether or not they would like this to be there. And the average person went, "Oh my God!"
And so I didn't do it. But I think in retrospect, I should never have listened to them. I should have just done it. Because, I mean Beans basically layered on this facility that I had wanted to do anyway, but Beans did it as kind of an afterthought.
And because it's layered on as a naming convention, there's some things that don't fit together real well. And so, for instance, it would've made a lot of sense for the default protection for an instance variable to be private. And then the getters and setters, which the system would've known about at a much deeper level, to make them either public or package.
Light Bulbs on a Network
Bill Venners: About four years ago, I read an article where you described a Doobie Brothers concert that you went to. You said you were kind of looking up at the lights flashing and you saw packets flying across the wire, and I assume that's mobile objects. Could you clarify what that story was about?
James Gosling: We were having this debate about building these systems, and to what scale people would go. You know, would people go all the way down to the light bulb?
And I was sitting there on this Doobie Brothers concert sort of staring up. And they had all these robotic searchlights -- spotlights -- there are these MIDI-controlled lights that a lot of these folks use. And I could see that all the network wiring and all of these spotlights were robotically pointing at the appropriate place.
And I was looking up there and said, "Fuck, light bulbs on a network. This is serious."
This article was first published under the name An Interview with James Gosling in JavaWorld, a division of Web Publishing, Inc., June 2000.
Talk back!
Have an opinion? Be the first to post a comment about this article.
About the author
Bill Venners has been writing software professionally for 14 years. Based in Silicon Valley, he provides software consulting and training services and maintains a Web site for Java and Jini developers, artima.com. He is author of the book: Inside the Java Virtual Machine, published by McGraw-Hill.
James Gosling on Java, May 2001
A Conversation with Java's Creator, James Gosling
by Bill Venners
June 15, 2001
First published in JavaWorld, June 2001
Summary
Java's Creator James Gosling talks with Bill Venners about many topics, including complexity, simplicity inheritance, composition, JSPs, servlets, and more.
On Thursday, May 10, 2001 I peddled my bicycle up to Sun Labs in Mountain View, California to interview Sun Microsystems Vice President and Fellow James Gosling at his Sun Labs office. In this interview, Gosling gives his thoughts on complexity and simplicity, inheritance and composition, JSPs and servlets, and community design processes, and more.
Current Projects
Bill Venners: What have you been up to this past year?
James Gosling: Doing a lot less traveling. I'm not really going around preaching the gospel anymore. Folks are pretty converted these days. I hardly give talks at all now. I've almost exclusively switched over to doing long Q&A sessions where I get up on a stage and either people ask me questions directly, or I pull questions out of a fishbowl. For the last year I've been working at Sun Labs and ignoring all the usual corporate 'goo' that comes with working at a company.
I've mostly been working on developer tools. I took a little hacking vacation earlier this year to do a relatively sophisticated Web server. It's just a pile of JavaServer Pages that manage the labs and the corporate document archive. And that has mushroomed features like mad. But my real job has been developing tools. In particular, I'm interested in tools for people who have to write code.
Most developer tools try to shield you from actually writing code in constructing the GUI bits or the database bits. Yet when you do write code you usually get glass teletypes where high tech is keyword coloring. Really high tech gives you a bit of help as you're typing in names, but that's where it ends.
So my work lately has centered on refactoring ideas, where you view a program as an algebraic structure, and you start doing essentially algebraic transformations on the program. That's been a lot of fun.
Bill Venners: You mean algebraic transformations in the context of refactoring your program?
James Gosling: Yeah. One thing my tool will do right now is let you rename a class. Renaming a class at one level is really easy; you just change the name. But how do you change all the references to that class and all the imports? And what about renaming when it includes moving a class from one package to another? I did all this stuff to rederive all the import lists in order to deal with the various naming issues. But it's going even further. This is prototype number three, or maybe number four.
Bill Venners: Will this tool be seen outside of Sun?
James Gosling: Yes. If it gets to the state where it looks like it might have even a vague chance of being interesting. My hope is to throw it over the wall some day.
The Complexity Challenge
Bill Venners: In several recent interviews, you claim that the main challenge for programmers is complexity. Can you elaborate?
James Gosling: In some sense, that's what this tool I am building is all about. How do you write a complex application? How do you deal with an application that's a million lines long? How do you even come close to understanding it? How do you make a change to a system like that? How can you cope with it?
Another axis of complexity exists as you lay the application out on a network. One of the things that Java is good at is giving you this homogeneous view of a reality that's usually very heterogeneous. One of the things going gangbusters recently is the cell phone business. The last time I heard a number, it was like 60,000 Java cell phones were being shipped every day. The numbers have become staggering. And that's not the highest volume Java platform. The highest is actually smart cards, and that's a really big number, although I don't know the exact number.
People building these applications that span the network from edge to center to edge, where you have part of the application in whatever the edge device is -- whether it's desktop or cell phone or PDA -- some bits and pieces in the infrastructure, and some bits and pieces in the back ends and the databases. One person can work from end to end, but how do you manage the complexity of that?
We don't have really good ways to deal with that issue. We just barely have tools that let us look at what one system is doing and map that across an end-to-end architecture. There are people who have these embedded debuggers for dealing with things like J2ME devices. How do you debug code that's inside your Oracle database? How do you look at the whole thing in totality? That's the hard and interesting problem. The systems being built get more and more complicated every day.
I spent a lot of time a couple of years ago on the whole real-time effort. The motivation for that came entirely from the real-time community. The main issue was that programmers are not writing a few thousand lines of assembly code anymore. These systems are getting really huge. And Java has proven to be pretty successful in building large reliable systems.
Bill Venners: I'm glad I asked that question because I thought you might have been talking more about the complexity of large, monolithic programs.
James Gosling: Yes, even isolated things. Some of these isolated applications that sit on one machine are a million lines of code. How do you deal with that? Most people have no way to wrap their head around it. There are all kinds of tools available, from organizational tool you get from object-oriented methodology, to some of the tools that are based on that, like UML modeling.
But of course the more tools you build to cope with such complexity, the more complex things become. We always strain at the limits of our ability to comprehend the artifacts we construct -- and that's true for software and for skyscrapers.
Bill Venners: Increasing complexity is also being driven by hardware that's getting cheaper and more powerful.
James Gosling: Absolutely. One of my favorite lines is that computers are driven by Moore's Law, which is an exponential process, and human beings are driven by Darwinism.
Bill Venners: And that's a linear process or what?
James Gosling: One way to look at it is as a Monte Carlo process. In Monte Carlo algorithms, the precision of the result doubles as you double the amount of time. So you're getting better on a square root kind of a curve, whereas computers are going on a two-to-the-N kind of curve. Their curvature points in opposite directions. How do people with skulls of a limited size deal with that?
The Role of Simplicity
Bill Venners: The opposite of complexity is simplicity. I have often heard you describe your philosophy when designing Java in the early days: you didn't put something in Java unless five people screamed at you and demanded it. In one interview, you told this really good story about moving to a new apartment and something about keeping things in boxes.
James Gosling: That's actually a general principle for life that works really well. When you move to a new apartment, don't unpack. Just sort of move in, and as you need things, pull them out of the boxes. After you've been in the apartment for a couple of months, take the boxes -- don't even open them -- and just leave what's in there and throw them out.
Bill Venners: The 'don't even open them' part is important because it's very hard to throw things away once you know what they are.
James Gosling: Right, because if you open them, you say, 'oh, I can't part with that.'
Bill Venners: So would you say that simplicity is a general philosophy programmers should always have when designing programs?
James Gosling: I think in any kind of design, you must drive for simplicity all the time. If you don't, complexity will nail you. Dealing with complexity is hard enough.
In programming language design, one of the standard problems is that the language grows so complex that nobody can understand it. One of the little experiments I tried was asking people about the rules for unsigned arithmetic in C. It turns out nobody understands how unsigned arithmetic in C works. There are a few obvious things that people understand, but many people don't understand it.
So one of the most important criteria for judging a design for me is the manual. Is the manual out of control, or is it reasonably concise? You can write a pretty decent Java manual in less than 100 pages. The current Java language spec is pretty thick, but that's because it's probably the most detailed language spec ever written. It goes through all of the details. I couldn't write the Java language spec.
A Delegation-Only Language
Bill Venners: When asked what you might do differently if you could recreate Java, you've said you've wondered what it would be like to have a language that just does delegation.
James Gosling: Yes.
Bill Venners: And we think you mean maybe throwing out class inheritance, just having interface inheritance and composition. Is that what you mean?
James Gosling: In some sense I don't know what I mean because if I knew what I meant, I would do it. There are various places where people have completed delegation-like things. Plenty of books talk about style and say delegation can be a much healthier way to do things. But specific mechanisms for how you would implement that tend to be problematic. Maybe if I was in the right mood, I'd blow away a year and just try to figure out the answer.
Bill Venners: But by delegation, you do mean this object delegating to that object without it being a subclass?
James Gosling: Yes -- without an inheritance hierarchy. Rather than subclassing, just use pure interfaces. It's not so much that class inheritance is particularly bad. It just has problems.
One of the metaphors I like to use for the whole design process is this game you see in arcades, particularly the older ones. If you go to the Santa Cruz Beach Boardwalk, there is this game called Whack-a-Mole. It's a table with 16 holes, and this little mechanical mole sticks his head out of one of the holes for a second. You whack it with a bat. He pops his head up, and you whack him, and he pops up someplace else.
Engineering design is like playing Whack-a-Mole. You have a problem sticking up over there. You go and whack it, and it goes away. But have you really fixed it, or has it just moved somewhere else? It's often hard to tell whether you've solved the problem or moved the problem. And more often than not, when people say they've solved the problem, they've just moved the problem. So one of my big issues with things like delegation, although I feel like there's a right answer in there, is that delegation is going to have its own problems too. But it hasn't been used as extensively, so does it have more problems?
It's almost a truism that you never actually find a perfect answer to a problem. You just find the answer that has the least problems.
Inheritance vs. Composition
Bill Venners: Given that we have both class and interface inheritance in Java, do you have any guidelines you would recommend to people trying to figure out which one of these they should use? When is it appropriate to use class extension, and what is the trade-off versus interface implementation and composition? Or is that too general of a question?
James Gosling: No, it's not too general of a question. I just wish I had some good rules because it always gets kind of vague for me. I personally tend to use inheritance more often than anything else.
Bill Venners: Inheritance meaning class extension?
James Gosling: Class extension. I tend to use classes a lot more than interfaces, and I'm not sure why. I'll use interfaces for things that need to be really abstract and really clean -- something runnable or printable. It's almost like if the class name ends in a-b-l-e, then maybe it ought to be an interface. That tends to be the way I operate, but I suspect that I don't use interfaces as much as one probably should. And delegation is something that I do a lot under the sheets. One of the nice things about delegation styles is that the user of the contract can't tell.
JavaServer Pages vs. Servlets
Bill Venners: You said that for several months you've been working on the document archive and using JSPs. I was wondering if you have any words of advice for people who are using JSPs, servlets, tag libraries, and so on.
James Gosling: Probably the most important thing that whacked me in the face was that with the basic JSP model, you have a Webpage template, and you're filling in the blanks. I found that there were a number of places where that worked reasonably well; but for the most important things -- the most complicated and sophisticated pages -- I really only had one. It's like the whole system revolves around this one Webpage that morphs into just about everything, like the portal page at Excite or Yahoo. The page isn't a template into which you plug little things because everything is plugged together; everything is computed.
It's computed on the outside, and you piece together little fragments. If you try to use JSPs for that kind of a page, you'd find it feels like it's inside out. What you want to do is assemble little fragments by the computing results of database queries, and you have the user's profile to provide page layouts. For more sophisticated pages, JSPs tend to get in your way. Doing a servlet is much simpler. There's a lot more mechanism in a JSP to help you and support you. Servlets tend to be simpler in terms of what they provide you, but that simplicity comes with a huge amount of flexibility. My central Webpage quickly devolved into three or four lines, where almost everything is done in one line that invokes one method, and that one method constructs the whole page.
Community Design Process
Bill Venners: Two years ago, I asked you how the proliferation of network-connected embedded devices was going to change software, and you said, 'you can't sit alone in a room anywhere and write software. It's more of a social thing.' I've recently been involved in the Jini community, defining the process of how standard APIs will be agreed upon. In the very early days of Java, you were the benevolent dictator. And now the Java Community Process is running that show.
James Gosling: Right. These days I'm the fly on the wall.
Bill Venners: From your perspective, as the fly on the wall then, is there anything you could relate to us in the Jini community about process? What has worked in the Java Community Process? What hasn't? What can be improved?
James Gosling: One of the most important things is the notion of a reference implementation. The ink isn't dry on a spec until somebody has built it.
One continuing problem is the tension between having a bunch of engineers in a room designing and the organizations with their political agendas that turn it into this competitive marketing thing that quickly becomes dysfunctional. Generally, if the engineers can just sit down and do their thing, the end result will be higher quality. Then there's this problem that the word 'quality' has a point of view because various industrial concerns tend to look at it and say, 'well, it's not perfect for me.'
Bill Venners: I see. I don't know if it was Ron Goldman and Dick Gabriel, the guys who wrote the first draft of the Jini constitution, or where it came from, but from Jini's beginning there were two houses. One's a commercial house, which represents people who have invested real money in the technology. They want to have a voice in its evolution. And the other house is nerds. They simply care about technology -- they are the designers in a room. For a spec to be approved, it has to pass both houses. It's like an experiment to keep an appropriate balance of commercial and technical concerns. I'm not sure how well it will work.
James Gosling: It's pretty hard, but certainly the computer industry is filled with examples of places where the only people in the room were really the politicians, and the bits of technology that came out were really goofy. It's hard. I wish there was a nice answer, but anytime you have more than one person in the room, politics is everywhere.
Bill Venners: It becomes politics. Even in the room of engineers, you have to deal with personalities.
James Gosling: Yes. That's one of the things they never teach in school, and it ends up being the hardest part of any engineer's job -- the whole interpersonal thing. No matter where you are, you're dealing with people.
Interface and Contract
Bill Venners: Does an interface imply a contract?
James Gosling: Yeah, an interface certainly does imply a contract, through what one's notion of a contract is is pretty variable. The part of the contract that is embodied in the interface in Java is really about typing and what the parameters are. There are lots of other extensions to that. You could go into things like what Eiffel does with pre- and post-conditions. You can get into some pretty serious behavioral modeling.
One time I had actually done a bunch of stuff to try to figure out how to do that in Java, long before Java was actually launched. And I got hung up on wanting the contract specifications to be ones that are actually analyzable, rather than just a Boolean expression that gets evaluated. I wanted something you could actually do some theorem proving about.
Bill Venners: In other words, look at the formal contract specification and then look at the code and say, yeah, this code does that?
James Gosling: Well, actually doing that all the way is--that's the fantasy of the folks in the formal verification field. And by and large, those people have been butting their heads against the wall so hard for so long that they have given up on the ultimate fantasy. But there are things on the way there that feel pretty valuable. I never got happy with doing something like that, and then we had to ship something.
Bill Venners: So the contract for Java classes and interfaces ended up being a human language description.
James Gosling: It's pretty much text, yeah.
Bill Venners: So as a programmer, I have to read that text and understand it. If I implement that contract myself, I have to make sure I do it correctly.
James Gosling: Right.
Bill Venners: And then if someone someone writes to that interface, they have to make sure they are not making any assumptions that are not beyond the scope of the contract.
James Gosling: Right, right. The Javadoc stuff I put into the original compiler in the very beginning. It's funny, you talk to tech writers about Javadoc and they say, "it's so horrible." A good tech writer can always do a better than the Javadoc can. And the answer is yes, that's absolutely true. A good tech writer can organize things and structure things. But having the text of the spec associated with the code deals with all kinds of synchronization issues. When you update the code, the fact that the spec is sitting there in front of you kind of forces you to be aware of the spec as you're editing. And heaven forbid, you might actually decide to conform to it, or edit it if it's changing.
That is one of the central problems with all of the mechanisms that people put together for doing interface contracts. How do you give people the discipline to actually maintain them? How do you have any idea that they are correct?
Bill Venners: That the contracts are correct?
James Gosling: That the contracts are correct. And in particular, how do you express all kinds of really subtle things. Just a Boolean equation that says, "stack depth is greater than zero," doesn't help much when you get to more complex APIs. And so English language text in many senses is woefully inadequate, but it does have the advantage of being clear, in your face, have some hope of being updated regularly, and it's very flexible.
Breaking the Contract
Bill Venners: Last year when I interviewed you, you said, "by golly, you have to fulfill the contract." Certainly if the next version of Java came out and they changed the meanings of all the methods in class String, it would break everybody's code. You're not supposed to ever break those contracts. The idea of a contract is: it's a contract. But are there situations in which I can sometimes bend a contract? Such as if nobody is actually using something, or it doesn't hurt too many people?
James Gosling: This is messy, right? If you are writing a bunch of code and the API is not exposed to people in the outside world, if you have this contained universe where you can actually see all the bits and pieces that reference something, then you're actually in a really great situation. Because you can do the kind of thing you just talked about. You can say, "This guy was never getting used."
One of the nice things about Java is that, at least for the language parts, people were using Java for five years before we released it. And it went through a lot of really big changes, because although there was a developer community of about 20 people, I could find every piece of source code in the world. And that let me do experiments to find things out.
One of the things I did was there were some issues with goto. Java had a goto at one point. I did this study of what people were doing with goto? And based on that study of a half million lines of code, I just got rid of it.
At one point I was doing a revision to the set of bytecodes. So I found every constant and figured out what integers people use commonly, what floating point numbers people use. When you have a controlled universe, a contained universe, that is such a luxury. And that's why I have this tendency to not release things real soon. Because as soon as you have users, all of a sudden, you have this problem.
In your question, you asked, isn't it okay to change things if nobody is using it? That's fine. You should be able to change things if nobody's using it. The hard part is, how do you know if nobody's using it? And how do you evaluate the consequences of that change? And once your user community becomes this kind of unknowable group out there, then you have published this contract. You don't actually know which are the parts you get to dicker with and which are the parts you don't. You know what you've promised the world, and by God you've got to live by it.
Exception versus Wrong Result
Bill Venners: Bertrand Meyer, in his Object-Oriented Software Construction book, talks about his philosophy of contract. If I'm a method and I say in my documentation -- or my preconditions, in the case of Eiffel -- that you have to pass me a positive int, then if you pass me a negative number, Meyer says it's okay if I give you a wrong answer back. Because you have broken the contract. What he wanted to avoid is you checking to make sure you're passing a positive number and me checking to make sure you're passing a positive number.
My take on Java's philosophy on that, however, is no, I should check for a negative value and throw you back an exception, so it's predictable what I do if you break the contract.
James Gosling: Yes, and actually what I think the correct answer is--and this is what I was trying to do -- was to make the contract evaluatable as much as possible at compile time. So that, where possible, you could actually say, "the value you're passing me is going to be negative or could be negative. Bad, bad, bad." Because when a contract violation is indicated by passing an exception, you don't actually see that until the code is actually running, which gives you this testing problem.
Whenever you're testing something, you have to make sure you actually exercise all these bits and pieces. And the world is filled with hunks of code that were written to handle some exceptional situation, and they have never actually been tested.
It may be that if you have a parameter check, "Is this a negative number?" it almost never actually happens that it's negative. It's the Ariane 5 problem. Remember the Ariane 5 failure?
Bill Venners: You have a link to that off your webpage.
James Gosling: Yeah. It like blew up. And that was because they had taken this one piece of software with a parameter in it that had to do with the trajectory. It was built for the Ariane 4, but the Ariane 5 had bigger engines, and the rocket was getting into the flat part of its trajectory while it was still accelerating. So numbers were coming out of range.
I believe it is completely beyond the sate of the art to try to do that kind of analysis statically, that particular one, but there are all kind of analyses that you could actually do. You don't declare failure if you can't do everything statically, but every thing that you can push into the static analysis phase of the system to get earlier and earlier is yet another source of reliability to the system.
Bill Venners: Interesting. Given what we have, then -- we have Java as it is -- what should we do to prevent our rockets from exploding? Should I, at the beginning of my method, just make sure you pass me good data and throw an exception? In either case we have a problem, especially if this is controlling a rocket, whether I give you a wrong result or throw an exception. Or let me ask it this way: Bertrand Meyer says an exception indicates a broken contract. What do you think of that?
James Gosling: I guess in the Java world, exceptions can mean lots of different things. Some of them are broken contracts. In the world of Throwable things that can be tossed around by the exception mechanism, there are two classes. There are the ones for which the checking algebra happens. I think those are predominantly the contract violations. But, for example, in the file I/O system, when you go to open a file and the file isn't there, you get an IOException. In that case, it seems to me that the exception is a part of the contract and you can actually handle it.
There are things that can go wrong for which it's actually reasonable to expect the application to be able to handle. And even outside of that, one of the things that people do a lot in Java if they are building a command dispatch loop, and it's invoking things that are plugged in, is wrap that call with a try catch Throwable. That will catch all kinds of errors, even the ones that are contract violations. That can be a really great way to increase the reliability of the system, because it gives you a way of saying, "Okay, this piece of the system just died horribly because it had a contract violation, but damn it, I've got to carry on."
So, in the Ariane 5 case, the problem wasn't actually that they had this range problem, because the range problem was only in this diagnostic system. The problem was that when the out of range value happened (and the out of range value happened on all of the computers, because they all had the same code) then they dumped ASCII -- I don't know if it was a stack trace or what -- out on this main serial line. And that serial line happened to go to the gimbals that controlled the motors. And so, instead of getting pointing angles for the engines, it was getting a stack trace and the gimbals went erh! erh! The engine went erh! And the thing just tore itself apart.
Bill Venners: That makes sense. It's a good justification for throwing an exception, because then I can catch Throwable. If you just give me the wrong answer, I'm not going to know.
James Gosling: Right. And in systems that have to be long lived and reliable, they have to have a comprehensive strategy for dealing with failure, because failure always happens. There will always be bugs, there will always be pieces of equipment that get smacked. There will always be alpha particles that hit busses. Things go weird and the average answer, which is to just roll over and die, is not a useful one. And particularly as you get into the systems like flight avionics, you just don't get to crash.
Bill Venners: You don't get to crash.
James Gosling: From the software's point of view, you have to keep on going, you have to do something sensible. You can't just say, "Oops, no, I'm not going to work anymore."
Assertions versus Exceptions
Bill Venners: In 1.4, assertions are due to come into Java.
James Gosling: Yeah.
Bill Venners: I'm curious when you would use assertions versus when you would use exceptions.
James Gosling: Assertions are just a syntax for generating exceptions. When an assertion fails, an exception gets tossed. So, an assertion in Java is essentially: if this funny condition isn't true, then throw an exception. At its heart, that's what an assertion is.
Standard assert macros in C and C++ have all done basically that. So the assert statement is not actually adding anything really new. What it's adding is a somewhat easier notation, and there's some other stuff under the sheets for enabling and disabling them.
Bill Venners: If the main purpose of assertions is to streamline the process of me checking for things and throwing exceptions, should I remove that at run time?
James Gosling: One of the nice things about the way Java works is that in general people ship around Java class files and the compilation phase happens just in time. These JIT compilers are all over the place. One of the really nice things you can do with that, which the assertion facility uses very heavily, is the code you ship around has the assertions in it. Assertions look like: if my gnarly test fails, then throw the exception. It gets turned into roughly: if assertions are enabled and my test fails, throw the exception.
And the first clause in there, the "if assertions are enabled," is generated in such a way that most just-in-time compilers will go, "Oh, that is statically false, so false and anything is false, so I don't have to evaluate the assertion condition, and since the if is false, the then clause can never be executed." So the whole thing just drops out. You can deliver your code with all the assertion tracking enabled in it, then, and at run time when you go to launch the app, you can say, "Turn off assertions."
Bill Venners: To improve performance?
James Gosling: To improve performance. And one of the great beauties of that is you can deliver one library to people rather than a debug library and a regular library. And they can decide.
Too Many Little Objects
Bill Venners: In an interview I read, you were asked what's the most common mistake Java programmers make, and you replied, "creating too many little objects." I wanted to get more information about what is too little and what is too often instantiated for an object. If I am making this big API or writing a program, to what extent should I worry about how big my objects are and how many of them I'm creating? And isn't that a performance versus ease of use tradeoff?
James Gosling: Often systems that have lots of little objects are easier to understand, easier to maintain, a lot cleaner. That's often how people get there is they have taken courses on building nicely structured systems. They do that, and the system is nicely structured. But then a little later, you do some performance benchmarks and almost always, there is not a problem. But every now and then, you find that holy mackerel, I went to do something really simple and I'm 27 levels deep in methods. There was an app I was looking at the other day where the guy was building this data structure and the way he did it, he eventually doubled the storage consumption.
Immutables
When to use and why
Bill Venners: How about immutables? When should I use immutables versus non-immutables?
James Gosling: I would use an immutable whenever I can.
Bill Venners: Whenever you can, why?
James Gosling: From a strategic point of view, they tend to more often be trouble free. And there are usually things you can do with immutables that you can't do with mutable things, such as cache the result. If you pass a string to a file open method, or if you pass a string to a constructor for a label in a user interface, in some APIs (like in lots of the Windows APIs) you pass in an array of characters. The receiver of that object really has to copy it, because they don't know anything about the storage lifetime of it. And they don't know what's happening to the object, whether it is being changed under their feet.
You end up getting almost forced to replicate the object because you don't know whether or not you get to own it. And one of the nice things about immutable objects is that the answer is, "Yeah, of course you do." Because the question of ownership, who has the right to change it, doesn't exist.
One of the things that forced Strings to be immutable was security. You have a file open method. You pass a String to it. And then it's doing all kind of authentication checks before it gets around to doing the OS call. If you manage to do something that effectively mutated the String, after the security check and before the OS call, then boom, you're in. But Strings are immutable, so that kind of attack doesn't work. That precise example is what really demanded that Strings be immutable.
Bill Venners: How about the wrapper types? I was asked a couple of weeks ago, "Why are wrapper types immutable?" I wasn't exactly sure what to say.
James Gosling: Same answer.
Bill Venners: Because you can, and it helps with caching?
James Gosling: Yes.
Bill Venners: Okay. The tradeoff seems to be that sometimes I may end up creating a lot more little objects.
James Gosling: You may. One of the proposals that keeps surfacing -- I actually wrote up a proposal for this four or five years ago. It's something that happened after Java got released, and so it gets really hard. And this one has really resurfaced with a vengeance lately: this notion of strengthening the support for immutables.
Another thing about immutable objects: if you have a class that's final and whose fields are final, except for one nasty problem, the optimizers can do really cool things with them, because they don't necessarily have to allocate them in the heap. They can have pure stack lifetime. You can copy them at will. You can replicate them at will, which is what happens with primitives.
That's one of the reasons that primitives are not objects, because it is so nice to be able to just replicate them. When you pass an integer to a method, you don't have to pass the pointer to that integer. You can just replicate that integer and push it on the stack. So, it's a different integer. The same value, but a different integer and you can't actually tell. And if you look at a complex number class in C++ versus complex numbers in Fortran. In Fortran, they do all kinds of goofy things allocating complex numbers to registers, which really doesn't work in C++. And that mostly has to do with the fact that in C++, they are still objects and they have an identity. It's this whole platonic thing about identity. The nit that causes problems with optimizers and immutable objects is that as soon as you have a notion of identity that is independent of the value, then various things get really hard.
Wrapper types versus primitive types
Bill Venners: Why are there primitive types in Java? Why wasn't everything just an object?
James Gosling: Totally an efficiency thing. There are all kinds of people who have built systems where ints and that are all objects. There are a variety of ways to do that, and all of them have some pretty serious problems. Some of them are just slow, because they allocate memory for everything. Some of them try to do objects where sometimes they are objects, sometimes they are not (which is what the standard LISP system did), and then things get really weird. It kind of works, but it's strange.
Just making it such that there are primitive and objects, and they're just different. You solve a whole lot of problems.
Platonic Identity
Bill Venners: Earlier you said "the whole platonic thing about identity." What does Plato have to do with identity?
James Gosling: The notion of identity is something that the philosophers have argued about for a gazillion years. One of Plato's things, I don't remember the names, but the basic story is you have Bob the fisherman. He's out there fishing. His boat springs a leak. He goes to see his friend Fred, who fixes boats. Fred pulls a plank off of Bob's boat and puts a new plank in. Bob's now happy and he goes away. His fishing boat is now fine.
A month later, the same thing happens again. He goes to his friend and after several years of doing this, every last plank in Bob's boat has been replaced by Fred. And so, now you have a whole new boat. Is this still the same boat? Then the trick to it is, unbeknownst to Bob, Fred has been saving all the little bits of wood that he has taken off of Bob's boat. And he's put them back together again.
Bill Venners: And he wants to swap.
James Gosling: So, which is Bob's boat? That with different names is one of Plato's things.
Static Methods in Interfaces
Bill Venners: Another question that I was recently asked is, "Why are there no static methods or non-public methods in interfaces?"
James Gosling: There almost were. At least, they almost were static methods. And non-public probably would make sense. I actually don't think there is a strong rationale now. At one time, there was kind of a delirious period, at least for the requirement to do public.
Static is kind of different in that one of the things I was trying to get to was that interfaces were sort of purist specification, no behavior. And it felt to me like there was a sort of a cleanliness to saying, "interface purely." And actually, that has often worked out pretty well.
There is still part of me that says, maybe interfaces should never have existed. People should just use classes for interfaces. But there turned out to be some nice things that get done with interfaces that are different. There's an interesting performance difference that most people never think about, which is that interfaces need to do a kind of a dynamic dispatch, whereas strict classes don't. The class model in Java is really rather reactionary. It's almost exactly the original class model from Simula 67. And one of the nice things about that model is you can make method dispatch just fiendishly fast.
There are all kinds of tricks for doing interface-style dispatches, flexible multiple-inherited dispatches, pretty fast. But they are always a couple of instructions longer at least and maybe more, depending on how you it. Although there are techniques that trade it off against memory. You can actually get it to the same performance as single inheritance, if you are willing to basically spend more RAM building tables. But one of the unsung nice things about the difference between classes and interfaces is that it is statically knowable whether you can do dynamic versus static dispatching.
Challenge of Change
Public versus Private Consumption
Bill Venners: You were talking earlier about complexity being the major challenge for programmers. The main other thing I think of as being a major challenge for programmers is dealing with the uncertain future and the changes it will require.
James Gosling: I guess one of my deals is that the word complexity covers a whole lot of ground for me, including the complexity of dealing with the future. The future becomes this great unknowable. One other thing we talked about earlier was the luxurious situation that some people are in when they are building an application, and they are the only people who will see the code. They are running it for themselves and that's it. When it comes to dealing with the future, those folks have a better situation. They can speculate the directions in which they might want to go. So they build the foundations for things they might do, given that they have the guts of the thing open right now.
But where life gets really hard is for people who are building APIs for public consumption, which is most of what happens in the Java software organization. All of the people who are doing APIs in the JCP, APIs like Swing. One of the reasons that Swing is so incredibly complex is that it has to serve 3 or 4 million masters. There are all these folks doing all kinds of different things, and when you are coming up with the API, if you come up with some speculation of the form, "Gee, I think somebody might want to do this," you're probably right. Even for arbitrarily bizarre values of "this." And it can be really difficult to keep things small when the domain that it's going to be applied to is so very large.
Binary Compatibility
Bill Venners: One thing you seemed to really care a lot about in Java was making it possible to make changes once you have frozen a particular API in stone. You've released it. You've thrown it over the wall. Now you really can't change it in a way that will break those peoples' code, but there are a bunch of changes you can make that are binary compatible.
James Gosling: That are binary compatible, right. I was searching everything I could find that I could come up with a decent way to implement that would allow you to evolve and still maintain binary compatibility.
Probably the central thing in that is in the virtual machine spec. The central thing is really about dynamic binding rather than static binding. The whole notion of having a just-in-time compiler has a whole lot of different aspects to it. One of them is this issue that if you look at a Java binary, it doesn't have fixed offsets for fields. It doesn't have slot numbers for virtual function tables. It's got symbolic references. And they get bound essentially as late as possible. And that gives you a terrific amount of flexibility. Some things seem like they ought to be obvious, that you ought to be able to do them, like adding private members to classes. But in something that does static determination of offsets of fields, you can't do that. You have to do all of that stuff dynamically. It really makes the issue of evolution work a lot better.
Divide and Conquer + Hierarchical Composition
Bill Venners: To go back to the subject of complexity, I think there's an algorithm for dealing with complexity that in general people use and in software in particular it's used. If you have this massive complex thing, you chop it up in pieces to start with.
James Gosling: Right. Divide and conquer. It's been with us for years.
Bill Venners: And each piece is then a understandable amount of complexity. And that's one of the ways I think about what a class or an object should encapsulate. It should encapsulate an amount of complexity that if there is someone working on the guts, working on the implementation, they can understand it.
James Gosling: Right.
Bill Venners: And then you have interfaces to those parts. And in those interfaces, you raise the level of abstraction. You abstract away some of the details.
James Gosling: Right.
Bill Venners: For example, if someone peels of the back of my television set, they could focus on and understand the guts of the TV. They don't have to think about and understand the entire television broadcast system all at once.
James Gosling: Right.
Bill Venners: But when I use my TV, I just push on. And maybe when I push on, 30 things happen inside the TV. And maybe over on this other TV when I push on, 50 things happen inside it that are different. I don't have to know all that. I just think in more abstract terms of on - off. The external interface to the TV abstracts away much of the details of its implementation. So, if you think about pulling all these pieces together again, I can understand this complex whole in terms of the simpler, more abstract interfaces to its parts.
James Gosling: Right. It's the pair of intellectual tools that people have used since the dawn of time. One is the divide and conquer, splitting things up in pieces, so they are individually understandable. And then there is hierarchical composition, where you take these things and you wrap them and put them together in these more and more abstract concepts.
There are often flaws in that, though. There's a fancy word in here that I'm forgetting. But there is often this view that with large complex systems, you can deconstruct them, decompose them into their parts and then analyze them individually. In biology, that kind of view is one of the things that led to a lot of major mistakes. Because you have to take this ecological view, of viewing the entire system. Because if you just look at a leaf or a frog, it's almost impossible to understand that leaf in isolation. You have to understand the whole ecology surrounding the leaf.
And so, there's this dilemma. You really do need to split things down into pieces, but when you split them down into pieces, you have to understand that they don't make any sense in isolation. You can't forget the ecology within which they live.
And so this business of on the one hand decomposition, dividing and conquering and hierarchical composition, they actually go hand in hand because hierarchical composition, putting things together, is really the only way that we see large systems of things, because it lets us encapsulate their behavior. And in order to understand a little piece, we have to understand the rest of it and so, you may end up with this funny way of working where you never forget the whole system, but you might have some parts that you're thinking of decomposed all the way down to the iron. Other parts are conceptually more aggregated, so that you don't lose the perspective of how this thing fits into the world.
A certain amount of that manifests itself in the way that a lot of designs become iterative. You do one design, you see how it all comes together and you say, nyeah, I don't think so and you go back again. Because in an awful lot of systems, they might be these big hairy systems, but there's a nut in the middle, around which it all kind of rotates. There's one little technological detail that kind of makes it all work. 99% of the code you ever write is kind of do-whatever-you-want code, but there's something in the middle that's really crucial. You just have to get that one algorithm, that one data structure, absolutely right. And often you find that these things pervade entire systems.
Bill Venners: What things pervade? That little kernel of importance?
James Gosling: That one little kernel of importance. If you're building a text editor it's often either like the document representation or the redisplay algorithm. And the rest of the work rotates around that.
APIs versus Protocols
Bill Venners: Looking at the complexity of distributed systems, then, each process on the network is like one piece of this whole system. And the interface between those pieces has traditionally been a protocol. One of the things Jini does is use mobile objects to be a nexus between the client and the service. And that lets you raise the level of abstraction between the client and service. Now, when we define a protocol as our interface, there is some handshaking going on and then there's just data structures. And nowadays, XML is all the rage for structuring data. But in my protocol spec I have to talk pretty much about all the details of that data structure. The client-service contract is in terms of information. Whereas in an API, I'm talking about code, and the contract is more in terms of behavior.
James Gosling: Right.
Bill Venners: And the thing I think I can do with behavior is I can be more vague. I don't have to say how, just what.
James Gosling: Right. Almost always, the less you can say, the better off you are.
Bill Venners: Because?
James Gosling: Because every commitment you make is a piece of flexibility you've lost.
There is this duality between network protocols and interfaces. They are both kind of the same thing. They are a way for these two parties to communicate. When you deal at the level of a network protocol, you don't have to specify what the program interfaces on the other side look like. So that gives you the freedom to write a C API here and a Pascal API there and an Ada API there, and they can be completely different. They just have to arrange the bits on the wire exactly the same.
And then the dual of that is when what you specify is the API. And you say, this is what it is, and how things get between here and there is, who knows? And that gives you a tremendous flexibility to have different ways of moving things back and forth. So for instance with RMI, one of the reasons that it's so popular is you can play all kind of games in that space in between. One of the things you can do is, if the two sides happen to be on the same box or in the same address space, all the stuff in the middle collapses out and it's just a direct call. Whereas, in these other systems, often you'll find that you're encoding and decoding even though you're not moving the bits anymore.
But you can also play games with how you encode it. In RMI once upon a time you could put in all kinds of different encoders. You could put in a binary wire encoder. It was actually possible to write an XML encoder or an IIOP encoder. People don't do that much, but the ability to drop in your own encoder is basically there.
You get independence of what the actual transport mechanism is. And to a certain extent, you can blend these. Because if you are doing the interface version, you can decide to target a particular binary encoding or not. So, you can get hybrid ways of building things. Nobody actually does that, although the RMI over IIOP stuff is kind of in that space.
Bill Venners: Or for example, a Jini service proxy isn't necessarily doing remote procedure calls, so it could actually implement the service locally. Or it could talk to something across the network using any protocol. There are all these web service things that will probably be coming up in the next few years. You could wrap one of those in an object that has an interface. And when a client talked to that object, it would be using that XML-based protocol.
James Gosling: Right. So that gives you pretty tremendous flexibility.
Testing against the Contract
Bill Venners: Another thing you mentioned when talking about complexity was how do I understand the behavior of a large distributed system end to end when it's very complex. And I think it's worse than that, in that often the whole system doesn't exist. Because there are pieces that haven't even been imagined yet or created yet, that will eventually hook into this.
James Gosling: Absolutely.
Bill Venners: So the whole system can't be tested together because parts of it don't exist yet. And another reason large systems can't be tested as a unit is that the parts that do exist can simply be too vast. The test matrix is too big. Too many clients and too many servers that want to talk to each other. So, one of the tools that I think Java itself uses and I think will be important in getting things to work together that can't be tested together is testing against the contract. Testing each piece against its contract.
Ambiguity in Specifications
James Gosling: Right. And that's fine as far as it goes, the problem being that you probably don't actually know what the contract is in some sense. There is no such thing as a complete contract. You can write more and more, but you'll always find that there is some little thing that wasn't really expressed in the contract, however it is an artifact of the way that one system behaves that some other piece depends on.
A standard thing that nobody ever puts in their contract is stuff about timing. You have a container class of some sort. It just happens to be that this container that we use over here does insertions really really quickly. Something else that might be totally compatible with it might have been optimized so you can do lookups really quickly, but insertions are kind of slow. And a lot of the time, that won't matter at all. Some of the times, it will be a killer.
Bill Venners: Yeah. You said there will always be failure in the code. In the contracts, there will always be some ambiguity. There will be some question that I have when I am working on my application, and I go look at the spec and it's not addressed. So I don't know what the answer is. So I have to guess. Someone else on the other side of the world may have the same question, and make a different guess. And now our stuff won't work together.
James Gosling: Right. Big problem. And in some sense, that is completely unavoidable, but you do what you can to make that happen less and less. I wish there were such a thing as a perfect answer to that question. There is this whole thing about mathematic specification of behavior and that ran into all kinds of troubles. One of its problems was that it didn't actually solve the problem, it moved the problem.
Bill Venners: Because now you have to figure out what the semantics of the mathematical formal specifications are?
James Gosling: Right. So, it doesn't actually provide an actual accurate specification. What it provides you is an alternate specification written in a different way. At least you can cross check the two and see if they make sense, but in no way is it necessarily complete.
Bill Venners: And that's how I think of test suites, as an alternate form of specification. I could go out and buy the Java virtual machine spec and look at the Javadoc, and that's a specification for the Java Platform in a human language. And I can go code it up. But I can't call it's Java unless it passes this huge battery of tests.
And I think the combination of having a spec as well defined as people can make it -- which is never going to be 100% -- plus the tests, gets you, not 100%, but pretty far along the way. I write a servlet on Windows and I deploy it on Linux and I deploy it on Solaris, and it works.
James Gosling: Yeah, it works. It's actually pretty amazing.
Bill Venners: And my servlet and those Java Platform implementations were never tested together until I ran my servlet, but all those platform vendors ran their implementations through these tests against the platform contract.
Forcing People to Pass the Tests
James Gosling: Right. And that actually is one of the big sticking points that starts arguments between various folks. There are people who care about interoperability and people who don't. And by and large, we actually care. So we are pretty particular that if somebody wants to call something Java, by God it ought to actually run Java programs.
Bill Venners: I think there's a third category of people. Those who care about inoperability.
James Gosling: Yeah, well. There's this... Let's not go there.
Programmer Productivity versus Program Performance
Bill Venners: Okay. New subject. We've talked about complexity and performance and change. Another thing that matters, to some extent, is the productivity of the programmer. I was wondering to what extent programmer productivity was a concern or goal, how it entered your thinking, as you were designing Java. And to what extent did you made tradeoffs in programmer productivity versus program performance?
James Gosling: It's funny how some of these things like performance and reliability actually fit hand in hand with developer productivity. There's a folk theorem out there that systems with very loose typing are very easy to build prototypes with. That may be true. But the leap from a prototype built that way to a real industrial strength system is pretty vast.
By and large, I wasn't really concerned about how quickly you could slap together a demo. I was much more concerned about how quickly you could build a real system. And boy, strong typing is a great thing there. Anything that tells you about a mistake earlier not only makes things more reliable because you find the bugs, but the time you don't spend hunting bugs is time you can spend doing something else. I don't know what fraction of my life I blew away hunting down obscure memory corruption bugs in random bags of C code, but it's a lot. You can get a huge amount of developer productivity just out of making things less error prone.
Bill Venners: That's interesting, because the next thing I was going to ask about was weak typing and Python. Have you ever done anything with Python?
James Gosling: A little bit. Things like Python can be pretty nice. One of the issues with weak typing systems is they tend to be very hard to get them up to really high performance. In a lot of systems, for example, when integers overflow, they turn into doubles or big ints, or whatever. That means that adding a number together is not just an add instruction. It's: "Gee, are these guys both integers? Okay. Then I guess I can do an add. Let's get the integers. Oh, but this guy's a bigger number than that."
So an add isn't one instruction any more. I cared pretty deeply that a = b + c should almost always be compiled into one instruction on just about any architecture. And you look at any of the JITs today and they pretty much do that. a, b, and c get optimized in the registers. And that's what it is most of these days. So you pay an awful lot for weak typing.
Bill Venners: In performance?
James Gosling: In performance. There are certain forms of weak typing which can actually be pretty useful. If you have something where you are worried about numeric range overflow, or you have something that is mostly a small integer but occasionally turns into a 500 bit number, it's kind of nice to have it roll over. Statistically speaking, those are pretty hard to find. Most people are unwilling to give up their performance for that flexibility, at least in the production systems.
In a lot of systems, however, it just doesn't matter if you spend 10-20 times as long doing an integer wrap. And also, a lot depends on how much you can vary in the libraries. So, for instance, PERL is in some sense is a horrific language in terms of performance, because everything is based around strings. But if the stuff you're doing really is string processing, the weak-typing polymorphic dispatch of everything doesn't matter because all the computation you're doing is done in the string matching algorithms, and they have optimized the hell out of that.
And so, you can end up with systems that perform just fine, so long as the real work is being done in libraries and what you're doing in the language is stitching things together. But it does mean that the language then becomes something that you can't actually use for everything. You can't use it for writing a string matching algorithm in something like PERL. Without the built-in string matching algorithms, it would be pretty slow. Whereas in Java, the string matching libraries are all written in Java. In the world of mathematics, it's a property generally known as completeness. How much of a system can you describe in itself, without having to go outside the system? That actually works pretty well in Java. You can write all kinds of funky low level stuff and the performance is good enough.
Can't Hide the Network
Bill Venners: What are the challenges of using mobile objects?
James Gosling: It's the standard fallacies of distributed programming. When people use mobile objects straight out of the gate, they think mobile objects are like any regular objects. But you have to absolutely take into account things like the performance is different. At least 2, probably 3 or 4 orders of magnitude slower. And that's not just a minor annoyance at that level. That deeply affects your architecture.
Bill Venners: You mean, if that object is doing something back on the network?
James Gosling: Yeah, so if you have an array or an object that represents and array. Pinging that thing for every element can be expensive. It might actually be cheaper just to make a local copy of the whole frigging thing in one transaction.
But also, there are issues like errors. If it's not a distributed object, not a remote object, people tend to -- and fairly legitimately can -- ignore all kinds of errors. And yet when it is a remote object, you have to pay attention to the fact that the network can go down. Things that are equivalent to that. The remote host can be hit by a meteorite. Or there are a vast number of things which are similar to being hit by a meteorite. Anybody who does programming in California these days...
Bill Venners: ...could be hit by a blackout.
James Gosling: I run Solaris on my desktop here and for the last 10 years, the #1 source of reliability problems has been the frigging power supply to the building. And when you are building a distributed system, talking to somebody else, there's this question of is he dead or is he slow? You can't tell the difference. Or did the network just go away and it will come back again? Or was it just glitch in the network? Did it just drop a few packets?
Bill Venners: That's what Jini really tries to address with leases and the fact that you can put RemoteException in your throws clause to say, "This method may do something the network, therefore, it might be slower or it might fail." And that way I'll know because it will throw me back this checked exception that I have to deal with.
James Gosling: Right. And that's really built into RMI.
Bill Venners: It's a philosophy of not trying to paper over the fact that there may be a network there.
James Gosling: Right, because if you try to paper it over, you're fundamentally kidding yourself. You just can't paper over either the performance issue or the error issue.
Challenge of Heterogeneity
Bill Venners: Another programmer challenge is the heterogeneity of hardware being programmed. This is particularly a challenge when creating mobile objects. The Java platform of course provides a great deal of homogeneity, but Java platforms are heterogeneous to the extent that different versions exist, different flavors exist (J2ME, J2SE, etc.), different API profiles exist, and so on. I'd like to be able to send out a Jini service proxy and when it lands, have it look around and dynamically load an implementation that makes sense. Could you speak to this and other strategies programmers could use to deal with heterogeneity?
James Gosling: The environmental differences from place to place get difficult to deal with. There have been a number of things that people have tried to do. This isn't exactly what you are talking about, but it's close, which is WebStart. In that, this mobile object, to use your term, comes along with a specification of the versions of the things it depends upon. It depends on a particular VM version at least. It needs the following add-on libraries. It needs the point of sale terminal and 3D rendering libraries. And that actually has been working pretty smoothly.
Bill Venners: I see. We used the same describe-the-requirements approach in the Jini Service UI spec. We don't actually send UI objects along with the Jini service proxy, we send a list of descriptions of available UI objects, including describing required packages.
James Gosling: Yeah.
Bill Venners: The client looks through the list and says, "This is a JFrame. I can't use that because I don't have Swing, but this here is a Frame. I do have AWT, so I could use Frame, except that over here it says it requires the speech APIs, and I don't have that." So the client looks through the list and picks a best-fit UI object. But a Jini service proxy, that one, it just goes and needs to work wherever it lands. Well, it doesn't have to run everywhere, it just has to run everywhere you care about.
James Gosling: Right.
Questions Never Asked
Bill Venners: Lastly, is there anything that people never ask you in interviews that you wish they would ask you?
James Gosling: People never ask me?
Bill Venners: Something that you would enjoy talking about?
James Gosling: In some sense, there are zillions of things that people never ask me. Generally, in interviews, people never ask me really geeky questions. By and large, I'm happy you're talking about really geeky things. This interview has been particularly geeky on the interview scale.
Bill Venners: I'll take that as a compliment.
James Gosling: So it's been a lot more interesting. Nobody ever asks me questions about tree attribution algorithms or what's a good representation for a parse tree -- basically things that nobody's interested in.
Bill Venners: Things the readers of the interviews probably don't really care about.
James Gosling:They don't care. It's not relevant to most people, but it's what I spend my days doing. Those are the kinds of things I find more interesting.
Portions of this interview was first published under the name A Conversation with James Gosling in JavaWorld, a division of Web Publishing, Inc., June 2001.
Talk back!
Have an opinion? Be the first to post a comment about this article.
About the author
Bill Venners has been writing software professionally for 14 years. Based in Silicon Valley, he provides software consulting and training services and maintains a Web site for Java and Jini developers, artima.com. He is author of the book: Inside the Java Virtual Machine, published by McGraw-Hill.
James Gosling on Java, February 2002, Part II
A Conversation with Java's Creator, James Gosling
by Bill Venners
March 25, 2002
Summary
Java's Creator James Gosling talks with Bill Venners about the current state of the Java language.
On Tuesday, February 19, 2002, I interviewed Sun Microsystems Vice President and Fellow James Gosling at his Sun Labs office in Mountain View, California. JavaWorld has published Part I of this interview. Since the interview was so full of interesting bits of James's wisdom, I requested and JavaWorld was kind enough to let me publish the rest here.
When James Gosling is not out preaching the virtues of Java technology, he spends his days in a quiet corner office at Sun Labs, dreaming up new ways to help programmers manage complexity. Bill Venners recently visited Gosling in his office for his annual JavaWorld interview. With his Borg mask (donned at a prior JavaOne keynote) staring down from a shelf above him, Gosling discussed semantic models, mobile behavior, abstraction versus vagueness, the importance of testing, and repetitive stress injury.
Semantic Models
Bill Venners: Someone once asked you what innovation felt like, and you said, "Well, it's not like a light bulb going off. It's more like there's something irritating you and you fix it until it goes away." What is irritating you these days? What things are you trying to make go away?
James Gosling: Lately, I've actually been spending about half of my time on, sadly, being corporate spokesperson. In the time left over, during which I get to do my actual work, I've been creating software development tools based on semantic software models rather than textual representations.
What can you do with a piece of software when it's represented as a tree? There's a long history of trying to do this. People often try to build structure editors that way, but tend to fail for a variety of reasons. But some things work nicely in a structural representation, which is how you build a semantic model. So I've been fussing with what you can do with structural representation programs as opposed to textual representations.
Bill Venners: What is a semantic model, and why do you like to manipulate them?
James Gosling: The usual program representation that people manipulate is just text. What the program has to play with is the letters -- 'f' 'o' 'r' '(', and so on. That's what the data structure looks like -- just a series of letters left to right, top to bottom. If you want to get more information, you must extract it from that series, which can be very difficult.
When people talk about a syntax tree for a program, it looks a lot like a standard binary tree that people would learn about in school. But the nodes all have labels on them. There are things like, "This is a plus node. In the left and right shoulder are the operands of the addition." Then you start labeling the tree with more information: "This is a symbol. It came from that declaration. This addition node has this type because the operands have these types." Once you generate this tree representation, you then annotate it with all the information about types, variable declarations, variable lifetimes, method bindings, and the rest. That's generally called a semantic model, where you essentially have complete resolved information about the program's structure.
Bill Venners: Semantics means meaning. Are you perhaps trying to capture more of the programmer's intent than current compilers?
James Gosling: There's been a lot of debate about what it means to represent a programmer's intent. Generally, representations of that intent turn into some kind of mathematics, something that often gets sent into a verifier. Nobody has discovered a way to express high-level intent that is much better than modern programming languages. The mathematical preconditions and post-conditions tend to be relatively similar; their big advantage is often that you do things twice. If you're going to make a mistake, you often make mistakes in two different ways, so you can compare.
People have come up with techniques for doing certain kinds of semantic modeling, like flow charts and finite state machines. Some of these techniques have software representations; mostly they have significant limitations. Things like finite state machines are pretty good for representing things like business processes. Many systems that do business process modeling use finite state machines. They all have the problem of hiding a lot of complexity because they're not full-blown Turing equivalent languages. There are always classes of problems that you cannot solve with them . So, it tends to always devolve down to you have to use a general purpose programming language. How do you make a general purpose programming language more comprehensible, especially when the systems you're trying to manipulate are very, very large?
A lot of the stuff in Java is designed around building large systems, and people have built multimillion line systems with it. But still, given the state of the art in tools, these systems become very difficult to manipulate.
Bill Venners: I see. Is the point of using a semantic model then to make it easier to make changes to those large systems?
James Gosling: To analyze them, to understand them, to make changes to them. A wide variety of things are a lot easier when you have that kind of representation. There's one school of thought called refactoring. The refactoring camp has developed a lot of transformations. They're often simple things, like renaming a class. But if you have a system with a million lines of code and you want to rename one class, it becomes extraordinarily difficult. You have to find all the places that use that class, and only those that just use that class, not something whose name happens to look a lot like that class. It's similar to if you try to move methods around.
The refactoring school is a lot about what happens when you're trying to reorganize. This can end up being surprisingly important given the way systems evolve. Systems are almost never really architected in their entirety. What happens is you start with some system design that you architect, and then it grows. Most nice, clean architectures turn into some horrible nightmare given just a few years of growth. Refactoring is all about how you rearrange things and keep them tidy.
But you can do lots of other things with structural representations, like finding places where certain idioms are used and rewriting them, finding places where certain kinds of errors exist. You can do static flow analysis. Say you have an API that has a lock and an unlock method. You can say, "Find any path where I lock this data structure, but then I don't unlock it. Find all the if statements that can be turned into conditional expressions. Factor out this variable from that loop." You can do all kinds of interesting transformations that are very difficult in text, but very easy in a structural model.
Bill Venners: If I were to use your tool someday, would I build and use a semantic model of my program as I'm typing code, rather than the usual edit-compile-edit-compile cycle?
James Gosling: Yes, though in my current experimental test bed, you don't type in text.
Bill Venners: You just think?
James Gosling: It sort of slurps in your program and then you say, "Apply this transformation, apply that transformation." Right now I'm not trying to replace regular editors. I may actually do a little plug-in that lets you edit text in it. But right now, this is an experimental test bench. It's not something anybody would actually want to use.
Mobile Behavior
Bill Venners: When I first started learning about Java years back, the thing I found coolest about it was that you could send behavior across networks. And yet, so far, that aspect of Java doesn't seem to really be used that much. Do you agree?
James Gosling: The answer is yes and no. People often use it more than they think they're using it, or they're using it in different ways. That certainly happens all the time with cell phones. Software is dynamically loaded into cell phones all the time.
Bill Venners: Do you mean midlets?
James Gosling: Yes, they're the little software bundles called midlets. They're dynamically loaded into cell phones all the time. You can explicitly load them, but often they just sort of come. They get wrapped in their little secure sandbox where they can play. But the facilities actually show up in many different places. The average large-scale Java application these days has a very modular architecture, where a spine is the central architecture, and then all these modules plug in. They tend to plug in dynamically at runtime, so often there is some kind of configuration file that will say, "Okay, plug in all of these pieces."
If you look at the way app servers are built, that's all they do. There's the basic core of the app server. But the stuff you think of as your application is dynamically loaded after the app server starts up.
Bill Venners: But they're not usually loaded across a network.
James Gosling: How the bits are delivered is another question, but the basic mechanism for this on-the-fly, dynamic construction of things has been used heavily. The over-the-network part got messed up with the bizarre legal maneuverings that happened around applets. Within corporations, applets seem to be doing surprisingly well, even on the greater Internet. But we see them mostly as games. They've definitely taken a whack over the legal nightmare that has been everybody's relationship with Microsoft, yet they're still doing pretty well.
Abstraction Versus Vagueness
Bill Venners: In a previous interview, I asked you how abstract we should make contracts when we're designing the APIs. You said, "...as abstract as possible, because every commitment you make is a piece of flexibility that you've lost." Recently I encountered a problem involving a method called getBoolean in java.sql.ResultSet, which just retrieves a boolean value from a column. This method was being used in an API that I had purchased, and there was a bug. The code was calling getBoolean on an integer field in a PostgreSQL database, in which 0 was stored to mean false and 1 to mean true. The problem was that getBoolean was always returning false even if the value in the database was 1.
If you look at the getBoolean contract, it just says it gets the column's value as a Boolean. It doesn't say what to do if the database field is not actually a boolean, or if it is an integer field. The contract is abstract, but it's also vague. So I'm not sure where the bug is. It's probably in the driver. On the other hand, it may be a valid implementation to say, "Well, if it's not a boolean field because I don't have that in my database, I'll return false." The getBoolean contract doesn't disallow that interpretation.
James Gosling: I would guess that one was a bug in the driver, because that's a situation where it should have been tossing an exception.
Bill Venners: The getBoolean contract does say it should throw an SQLException if there's trouble accessing the database. In this case, though, there was no trouble accessing the database. The method could throw a runtime exception, but should it and which one?
Is there a difference between abstract and being vague? Should you be abstract, but not vague? In this case, I don't think it makes sense to interpret the contract as it's OK to return false all the time. But the contract doesn't say that you can't do that, because it's abstract. This particular implementation of getBoolean in the PostgreSQL driver returns a boolean value. It just happens to always be false when the database field type is integer.
James Gosling: Yes. This is one place where it is the art of computer programming. You need to specify as much as necessary for people to be able to use it correctly, but you don't want to over-specify things. It's very hard to do complete specifications. Almost nobody actually does specifications that are close to accurate. The only ones in the Java world that I think even come close to rigorous completeness is the Java language spec, and that's probably because most of the words for the current edition came from Guy Steele and Gilad Bracha, who are well-known totally anal freaks.
It takes a very special mindset to write specifications, and even so, Guy still gets upset. He's always finding hidden vagueness. So, in some sense, vagueness is inescapable. We're human, and you always have to interpret anybody's documentation with a certain set of reasonable-person filter to it.
Bill Venners: You mean, I have to be a reasonable person when I interpret the contract?
James Gosling: You have to say, "What would the reasonable correct interpretation for something be?" Invoking getBoolean on a field that happens to be an integer has to be wrong. Exactly how the system should respond to that is another question. People who actually implement it might have gone one way or another. But returning false always...
Bill Venners: ...is probably a bug.
James Gosling: I think anybody would agree it's the wrong thing to do.
On the other hand, you can also over-specify in subtle ways. For example, if the contract said, "getBoolean returns a new Boolean object that tells you whether the result is true or false," that has a piece of over-specification in it that can be damaging. It says it returns a new Boolean object. There are really only two values for Booleans in the world, true and false. So you can just have two Booleans in the entire universe, and you return a reference to one or the other. But all too often, because you have the word "new" there, you actually have to construct a new one. So, you have thousands or millions of instances of things that are all true Boolean objects.
Bill Venners: Or in my case, all false.
James Gosling: And that is an issue because the objects, besides having a value, also have an identity. So when you say, "This returns a new Boolean," you're also promising that each returned Boolean object has an identity distinct from any other identity. And that forces you into an implementation that consumes much more memory than necessary.
Bill Venners: That makes sense. You have to find the right place where you're being as abstract as possible, but no more abstract than is appropriate.
James Gosling: It's like this old Einstein quote, "Everything should be as simple as possible, but no simpler."
Importance of Testing
Bill Venners: What do you see as the role of unit tests, conformance tests, and any other test in software construction?
James Gosling: Tests are something that people have to take seriously. I would love for the state of the art in theorem-proving testing to be better than it is. But the techniques that actually work sort of combine unit testing and clean interfaces, where you actually describe how things interact properly. That increases the probability that if all the components pass their unit testing, you can put them together and the whole thing actually works. But you still have to test the whole thing, no matter how much unit testing and careful design you've done. I don't think anybody tests enough of anything. But that's sort of a truism.
In the J2SE (Java 2 Platform, Standard Edition) world, we put an immense amount of effort into testing. We have these huge test suites, tens of thousands of test programs that we run, large applications and small test programs. It consumes an immense amount of energy. Given the way people depend on Java these days, we absolutely have to do it.
One thing that makes testing difficult is that it's kind of boring. Most people think of it that way, but at the same time, it can be intellectually very difficult.
Bill Venners: How's that?
James Gosling: Trying to deal with subtle interactions between pieces that are miles apart. One of the things that goes on in Java is trying to minimize the places where that kind of interaction happens, so that it's easier to test. But lots of things are intrinsically difficult to test, like floating point arithmetic. You could still get a Ph.D. thesis for finding a good way to test, say, the sine function or the cosine function. It's amazing how subtle some of these things are, even though they seem simple.
Bill Venners: I think it's often hard to think of tests. In fact, sometimes it's impossible to test things, because they have to be true everywhere. It's like you can prove a theory wrong, but you can't prove it right.
James Gosling: Right. When I mention sine and cosine, a lot of these functions have this general property that's usually called monotonicity, where it always increases over some interval. Sine always goes up and then always down, and then always up and then always down. Given the vagaries of floating point arithmetic and rounding, if you aren't careful, the function will sometimes bump up and down, because of rounding. You can get interesting shimmies at a really microscopic level in the curve.
Nobody actually has a great way to test for monotonicity in these functions, other than essentially enumerating all possible values. But given 64-bit floating point, there isn't enough time in the universe to do that enumeration. So, people rely on constructing their algorithm so that they have, usually not a proof, but validation that the curve will be as smooth as possible.
Repetitive Stress Injury
Bill Venners: Now and then, my hands hurt. I try to pay attention to it and take it seriously. I have an ergonomic keyboard; I try to sit with good posture; and if things get painful, I stop typing for a while. I know you had a bad case of Repetitive Stress Injury (RSI) that was ultimately healed by surgery. Could you describe what happened to you and perhaps give advice to programmers who notice their hands or wrists hurting?
James Gosling: People really need to pay attention to their bodies, their hands, their wrists, their elbows -- the whole system -- because they can easily get out of whack. One big issue is not any particular problem, but that often you have multiple problems that interact and masquerade as each other. It was so bad for me because I basically had three independent problems -- or four or five, depending on how you count them -- that shared certain symptoms associated with pain in the arm and wrist. I had issues with carpal tunnel syndrome; most of its symptoms are about a pinched nerve. But there are other places where nerves can get pinched. So, I had issues in my carpal tunnel, in my elbow, my spine, and issues around my neck.
As for the neck issue, I had been in a car accident and had a whiplash injury, which caused my right levator scapula muscle to chronically inflame. That muscle apparently is positioned such that if it swells, it not only gets sore, but it pinches a nerve that goes down to your arm, making your arm hurt. And you'll think, "What did I do to my arm here?" But it has nothing to do with your arm; it's up here [in your neck].
You can get joint erosion problems by holding the joint at odd angles. Many hackers have injuries that are like tennis elbow, which in itself causes one joint to slightly dislocate, which can pinch a nerve there. You also have two bones that form a sort of face at the wrist, where all the little carpal bones are. If the one bone dislocates, the face isn't flat anymore, and that can cause tremendous pain in your wrist.
There are simple things you can do, like the way they teach you to hold your hand when you're typing spaces repetitively. You pull your thumbs back so that you have your fingers on the home row and then your thumb on the spacebar. That puts an unnatural strain on your thumb's lower joint where it extends into your palm. I had serious problems with this joint dislocating all the time and wouldn't know why. It would hurt like hell in my hand, and sometimes I'd notice a bump there. The bump was there because the bone was not in its socket.
Bill Venners: You dislocated your thumb by typing?
James Gosling: Oh yeah. It's remarkably easy.
Bill Venners: What would you advise to programmers? There's a lot of typing going on. What should we do to avoid problems?
James Gosling: Well, you certainly should watch out for posture issues and keyboard issues. Many people focus on the keyboard and get their keyboard set up pretty well, but then completely ignore their mouse. The mouse, if anything, is even more important than the keyboard. Often, people will have the mouse up on the side and they'll crank their wrist to use it. When you have your wrist really folded and you're trying to do detailed motions, it can really aggravate the whole carpal tunnel.
In some sense, the dumbest thing I did was avoid getting treatment. I actually had carpal tunnel surgery done on my wrists, and I really should have done it a lot earlier. Fortunately, it wasn't too late. The carpal tunnel is a place where the nerve gets tightly squeezed; apparently, if it's squeezed heavily for a long period of time, the nerve will just die. And once the nerve's dead, it ain't coming back. So, it's then permanent.
Many issues that people have with the carpal tunnel will go through the standard succession of problems. One day you'll feel some numbness in your hand, and you go to your doctor, who says to you "Wear this brace." And that'll make the problem go away. What's happening is you've had some swelling in your carpal tunnel, and by putting the brace on, it stops you from abusing it. The swelling goes down, but then the sheath around the tendons will grow a bit. You'll find that over time, the quick fixes like wearing a splint are less effective. Pretty soon, your hand is just a piece of meat. You can't do much with it that requires the small motor muscles.
I got to the point where I really couldn't sign my name. I had to learn to write. I could kind of grasp a pen, but I couldn't do side-to-side motions in my fingers, because that mostly requires your small motor muscles, which you lose control of.
Bill Venners: You lose control of them or it's too painful?
James Gosling: You lose control of them. You can do anything that uses just the tendons. I could make a fist, but I couldn't spread my fingers. I learned to grab a pen and then use my elbow and shoulder. I could kind of write, but could just barely sign for lunch.
Bill Venners: I've heard of people who can't turn keys anymore.
James Gosling: It's not so much turning the key, but can you actually manipulate your hand into a position to hold it, at least for a carpal tunnel issue.
For me, the thing that made a difference was finding doctors who could deal with the system rather than a particular problem. All these problems look the same from the symptomatic point of view, namely your hand, your wrist, or your forearm hurts. And it's often a fairly generic hurt. When it comes from a nerve pinch, the nerve pinch can be anywhere. So, doctors can say, "Try this or try that." A hand specialist will look at it and say, "Well, the nerve propagation delay across your carpal tunnel isn't too bad, that can't be causing your problem," and, "Well, the nerve propagation delay across your elbow isn't too bad, so that can't be causing your problem," and "The nerve propagation delay up there isn't too bad, so it's not causing a problem." But when you add them all up, it's a problem.
Bill Venners: That reminds of what we talked about last time. That to understand large, complex software systems you have look at and understand individual pieces, but also understand how those pieces interact to form the whole system.
James Gosling: Yeah, and one of the sad things about modern medicine is that the doctors tend to be pretty specialized. The specialization is completely unavoidable. There's just so much knowledge. You could spend your whole life just understanding hands or elbows.
Talk back!
Have an opinion? Be the first to post a comment about this article.
About the author
Bill Venners is president of Artima Software, Inc. and editor-in-chief of Artima.com. He is author of the book, Inside the Java Virtual Machine, a programmer-oriented survey of the Java platform's architecture and internals. His popular columns in JavaWorld magazine covered Java internals, object-oriented design, and Jini. Bill has been active in the Jini Community since its inception. He led the Jini Community's ServiceUI project that produced the ServiceUI API. The ServiceUI became the de facto standard way to associate user interfaces to Jini services, and was the first Jini community standard approved via the Jini Decision Process. Bill also serves as an elected member of the Jini Community's initial Technical Oversight Committee (TOC), and in this role helped to define the governance process for the community. He currently devotes most of his energy to building Artima.com into an ever more useful resource for developers.
与Java创始人James Gosling十分钟的对话,改变一生
1:最开始,专攻一门语言
开始学习一种语言时,就安安心心的学习,不要在一开始就想同时掌握不同的语言。
学习语言最重要的一点,就是处于一个相对单一的语言空间,同时,编程语言也是同样的道理,我们每一个教授都说,别想一口气吃个胖子,先学一门语言!
2:多问,尽一切方法去问
高手比想象的要多,当你遇到问题时,就厚着脸皮去问,尽一切努力去问,不及手段的去问。
当时我看到James的时候,我不管3721直接冲上去,问了他一大堆问题。事后,没有人会记得那个问题的人,但是如果不这样做你的问题不会得到解决。在学校里也一样,每个人都交钱了,为什么不问教授呢。
网络论坛也有很多高手,而且很愿意帮助大家。
3:多读
编程书有很多,当然大学时的课本必须要读,但是光一本教材是不够的,需要不断的去读,因为有时候,有些书在一个问题点解释的很好,但是在另一方面解释的就略有欠缺,所以可以去看别的书,不断的将自己的知识丰富起来。
如果是一个宿舍的话就不要买一样的书,每个人买不同的书,然后借换着看。
4:看新闻,学会分析IT未来局势
学习为的是什么,对于绝大部分人来说是找工作,所以要知道你所在的行业的行情,万一你学的语言、软件、技术、行业将来会被淘汰,那么之前所有的努力都白费了。
学会读新闻、看新闻、分析新闻,分析什么技术会火,什么技术会长久,什么样的公司发展平稳等等等等,不然如果一直编程,即使再厉害也只是一个码农。
5:至少学会两门语言,当然三门以上更好,但是至少要会两门
对于将来谁都没有百分之百的把握,自己所学的语言是否会被淘汰,所以最好要留个后手
6:编程,优化,再编程,再优化
世界上没有最佳的完美程序,越快,越简单,越好。
对九个超级程序员的采访
在一个炎热无聊的下午,我突发奇想。我想通过电子邮件的方式对那些我非常感兴趣和非常敬重的程序员问10个问题。准备这10个问题我只花了5分钟,这些都是我个人想问他们的问题,所以,我基本上没想太多要问他们什么。最后两个问题和编程没有什么关系,我就是想问题这些人的一些兴趣爱好。
这篇访谈源自2006年,最先发布在波兰程序员 Jaroslaw “sztywny” Rzeszótko (AKA “Stiff”) 的博客上。但是这篇博文现在找不到了。非常感谢他能授权我重新发布这个博文。
在一个炎热无聊的下午,我突发奇想。我想通过电子邮件的方式对那些我非常感兴趣和非常敬重的程序员问10个问题。准备这10个问题我只花了5分钟,这些都是我个人想问他们的问题,所以,我基本上没想太多要问他们什么。最后两个问题和编程没有什么关系,我就是想问题这些人的一些兴趣爱好。另外,不是每一个人都想回答我的,这是我第一次做“访谈”,所以,我犯了一些错误,一些问题没有得到回答。不管怎么样,我得到了很多很有意思的内容,所以,这对我绝对是一次很有意义的经历。
并不是每一个人都回了我的邮件,也并不是每一个人都同意回答我的这些问题,也许在我发布这篇文章后我会得到那些回答,但是我已经迫不及待想把这些东西发布了,所以,我可能会更新这篇文章(更新:2006年3月8日,我收到了Bjarne Stroustrup的回信)
– Jaroslaw
介绍
Linus Torvalds - Linux kernel 作者。
Dave Thomas – “Pragmatic Programmer”(注:douban) 和 “Programming Ruby”(注:douban) 以及其它一些优秀书籍的作者。 你可以在 这里 读读他对编程的一些想法。
David Heinemeier Hansson – Rails Framework 作者- 一个目前最新最热的Web开发框架。他的blog在 这里. (陈皓注:他也是37signals的领导人之一)
Steve Yegge – 他可能并不那么知名,但是他给了很多有意思的回答。他有一个很火的关于编程的 blog,他也是游戏 ”Wyvern” 的作者。(陈皓注:他最火的是去年在google+上对google和amazon的吐槽,06年他应该在google了)
Peter Norvig – Research Director at Google, 知名的 Lisper,AI书的著名作家,个人主页。
Guido Van Rossum – Python 发明者。
Bjarne Stroustrup – C++发明者, 个人主页。
James Gosling – Java 发明者。
Tim Bray – XML 和 Atom 规格说明书作者之一 个人博客 。
Q 1: 你是怎么学编程的?是从学校里学的吗?或者你没有上过学:) ?
Steve Yegge
在我17岁的时候,我在HP的计算器中用他们的RPN 栈语言自学编程的。在这之前,我尝试过学习编程一两次,但都没有学成。HP 28c 和 48g 的科学计算器是一个很牛的东西,而且还有不错的文档。我搞了一本3D图形的书,并很费力地把其中的Pascal语言转成RPN栈语言,并用48g写了一个 3D的线框图渲染图。运行的还不错,在我买了PC和Turbo Pascal之后,我开始认真地学习编程。在我进入大学计算机科学专业之前,我已经是一个不错的程序员了。
我在华盛顿大学拿到了计算机科学学位,这绝对是有价值的,所以,我建议所有的程序员都应该得到计算机科学专业的学位。
Linus Torvalds
我没有在学校里学过编程,我在主要是读我自己想读的书,或是就直接去编程 (一开始在 Commodore VIC-20 学编程, 然后是 Sinclair QL上编程)。
当然,我觉得上大学非常有用。我没有去一个工科大学,我上了赫尔辛基大学,这是一个比较偏理论的大学,所以,那里的教育并没有那么多的编程的东西 (编程只是很少一部分),这里大多数的课程都倾向于教一些基础概念的东西,如:复杂性分析。看上去很无聊,甚至有点浪费时间,但是我还是觉得这些课有用, 我对大多数课都还比较enjoy。所以,我觉得我可能在这些方面是一个比较好的程序员。
David Heinemeier Hansson
我学编程是从用HTML做我的第一个网页开始的。那时,我想当我的网页能动态地显示一些内容,所以,我选择了ASP和PHP。在做完这个网页后,我知道了怎么去编程,于是我开始我的计算机科学和商业管理学位的学习。
Peter Norvig
我是从高中和大学课程中学编程的,但是我还是觉得我自己学得更多。
Dave Thomas
我是在高中学编程的。我完全地迷住了,我对编程爱得无法自拔,然后,我开始挑选那些提供软件开发课程的大学。最终,我去了伦敦大学的帝国学院。第二 年我就开始学习软件开发的课程了,那绝对是非凡的,学生和教员在一起工作把教材做得更好,每一个人都可以从中学到很多。这些课程给了我难以置信和非常雄厚 的软件开发背景。我在那里读到了博士,最后去创业了。
关于“我是怎么学编程的”这个问题,我的回答是“我现在还在学编程”。我认为好的程序员一生都在学编程。这并不是去学一门语言或是一个代码库,好的程序员会对他们的编程技艺一年又一年地精益求精。
Guido Van Rossum
我去的那个大学有一个大型主机和很多不同的计算机课程。这对我很重要。
James Gosling
起初,我是自学的。在我去上大学之前,我就找到了一份程序员的工作。但是我很高兴我去了大学,在那里有很多乐趣,最终我学到了博士。
Bjarne Stroustrup
我先上的是Aarhus大学, 然后是 剑桥大学(Cambridge),这两个大学教了我很多很有用的东西,这些东西为了以后的工作打下了基础。另外,我对编程和钱的关系学得非常好——知道了真实世界的问题,正确性,维护性,准时交付,等等,这些比教育可能更重要。
Tim Bray
我本来想去做一个数学老师的。但是,那个学数学的大学要我去学几个计算机的课。
Q 2: 你们觉得对程序员最重要的事是什么?
Steve Yegge
沟通能力(写和说)。除非你可以让你的想法更有效率地传递出去,否则你不可能做得比编程更多的事。程序员应该疯狂地阅读,锻炼写作能力,参加一些写作培训课程,甚至锻炼在公开场合演讲的能力。
Linus Torvalds
It’s a thing I call “taste”. 有一件事,我把它叫做“品味”。
我倾向于不从熟练程度来评判那些和我工作过的人。这些人能非常艰苦地写出很多代码,但是我想从他们对别人的代码的反应做出评判,这样我们就可以明白 他们自己写的代码怎么样,知道他们使用的方法怎么样。他们对别人的评判还告诉我,他们是不是有好的“品味”。是这样的,如果一个人没有“好的品味”,那么 他一般不会很好的评判他人的代码,他自己写的代码通常也不会很好。
哦,这并不只是唯一的事。还有一件事,尤其在开源项目里,那是他是否有能力能和别人进行简单的沟通,告诉别人他要干什么,怎么干。这个能力可以告诉别人为什么你干的事是非常重要的,并不是所有的人都有这个能力。
也就是说,有一些人可以写出很不错的代码,但他们并不一定能解释这些代码,他们也并不一定有好的品味,但是代码可以运行得不错。有时,你需要另一个 人(有那种不错的品味的人)把他的代码转成更好的形式。也就是说,任何一个程序员都需要那种可以用清晰的代码来解决复杂问题的基础能力。
David Heinemeier Hansson
很强的对有价值的事的感觉。你可以问问自己这个问题你有没有这种能力:我现在做的这个事值不值得做?很多程序员浪费了如大海一样的时间去做一些无意义的事。
Peter Norvig
我不觉得只有一个,如果要我说一个的话,我说是“专注”。
Dave Thomas
热情。
Guido Van Rossum
你的问题很难回答啊:-) 我猜,如果程序员会在早晨煎个鸡蛋做早餐,那真是无价的能力。
James Gosling
自我激发。你需要全身心地投入到你要做的事中。
Bjarne Stroustrup
把事想清楚的能力:程序必需要能清楚地理解问题并能清楚地表述解决方案。
Tim Bray
能为自己的直觉提供证据的能力。
Q 3: 你是否认为数学和/或物理是一种很重要的编程技能?为什么?
Steve Yegge
数学有很多的分支和程序员相关,他们是“离散数学”和“具体数学”。这些分支包括的学科有,概率论,组合数学,图论,归纳证明,和其它有用的东西。我会鼓励所有的程序员都去学习离散数学,无论能学多少,因为这总比什么都不懂强。
对于传统的数学,我也不经常用,但是我需要的时候这些数学知识会很管用。例如,在我之前的工作中我就用到了微积分。我需要估计每个小时中某服务的高 峰时间的流量负载,所以,他的负载是跟着太阳走的就像一个正弦曲线一样。最简单的方式就是把每个小时的负载曲线给整合起来。如果我不知道微积分,我就不知 道怎么更为准确地估计。
当年我在开发我的Wyvern游戏的时候,我的平面几何的知识对我非常有帮助。而且经常使用代数和线性代数的知识。但我很少在工作中使用三角学或微分方程,微积分同样也很少。
我想说,简单的数学基础让我的技能比一般程序员好过5%到10%。如果我了解更多的数学,我确信我会比今天做得更好,所以,我每周都会花几个小时学习数学。
我喜欢物理,我还在学习物理,我会花我一生去理解量子力学。但是我个却没有发现物理对我的程序员工作有多有用。当然,如果我从事一些和物理相关的工作,可能会有用,例如:3D游戏编程,或是某种物理特性仿真。
Linus Torvalds
我个人认为有很强的数学背景是一件好事。但我不确信物理是不是这样的,但是我深信懂数学的人会让你成为一个更好的程序员。这些智力模型都是相通的。
David Heinemeier Hansson
根本没用。至少对业务编程和Web应用来说没用。但是数学可能对一个人的写作有很重要的帮助。
Peter Norvig
是的。很多相法都是从数学来的:归纳,递归,逻辑,等等。
Dave Thomas
也许吧。但老实说,我没见到过懂这些学科和好的程序员有很大的相关性。
然而,我见过有音乐背景和好的编程技能有很强的相关性。我不知道这为什么,但是我怀疑大脑中的某个区域可以让人即可以写出好的音乐,也可以写出好的代码。(陈皓注:@Sir阿怪 貌似就是这个例子)
Guido Van Rossum
数学,当然(对于一些学科是很重要的,我不关心微分方程,但是代数和逻辑学是很重要的),物理,我不觉得对编程技能有关,当然物理在其它很多地方很有意思。
James Gosling
当然!数学教会了我逻辑和推导……让我有了一双懂分析的眼睛。当我们分析算法的时候,数学是无法被取代的。
Bjarne Stroustrup
这要看程序员自己和项目性质了。以前的数学很有用,物理一般,但是学好物理是是学习应用数学最好的一条路。
Tim Bray
对我来说,在我的编程生涯中我从来都没有用过大学里教的数学。
Q 4: 关于编程,你们认为接下来的大事是什么?X-Oriented编程,Y语言,量子电脑 ?
Steve Yegge
我认为Web编程会逐渐变成最最重要的客户端编程。而对于原来传统的客端端编程都会被废弃,如: GTK, Java Swing/SWT, Qt, 当然,所有的和平台有关的东西,例如 Cocoa 和 Win32/MFC/等。
当然,这不会一晚上就发生了。这会在第一个十年内缓慢地发生,而在第二个十年内,Web Apps最终会胜利。工具,语言,协议,和浏览器技术都会进步得非常快,并会完全超出你今天能干的事。每一年都会向前进一步,而从今天开始,我会最终决定 把我所有的应用开发全部切换到基于浏览器的应用。(陈皓注:我也是这么认为的,参看《来信,创业,移动互联网》)
微软和苹果最终不愿意这个事发生,所以,触发这个事的第一步会是一个开源的浏览器(如:Firefox)开始到了支配市场的地位,然后会出现某种Firefox的杀手级应用(这种杀手级应用可能会像iTunes一样,所有的人都会用它,只需要下载Firefox)
Linus Torvalds
我并不认为我们会看到一个“大的跳跃”。我们只会看到很多的工作帮助我们把那些沉闷辛苦的工作变得更简单——会有一个更高级别的语言,也许把简单的数据库集成到语言中来会是其中最主要一个。
例如,我个人相信“Visual Basic”在编程方面比“面向对象”做得更多。当然,人们都在取笑VB是一个很烂的编程语言,并且人们在谈论OO语言都十多年了。但我还觉得不是这样 的,Visual Basic 不是一个好的语言,但是我觉得VB那简单的数据库接口比OO更重要。
所以,我认为会语言有很多的改进,并且,硬件的改进会让编程更容易,但我并不期望会有巨大的生产力或是革命性的改进。
至少,你不会开始搞真正的AI的东西,我也不认为真的AI会变成某种你不需要编程的东西。
David Heinemeier Hansson
我从不试图预测未来。我也不相信命运一说。最好预测未来的方式就是去实现未来。
Peter Norvig
大规模的分布式处理
Dave Thomas
下一个最牛的事会被再下一个最牛的事所掩盖,然后再被再再下一个所掩盖,再再再下一个所掩盖……。这是一件没完没了的事,所以,我并不会试图去找最 牛的事,因为这会让人们忘了那些最真实的问题:把基本的东西做对。我们要让用户更满意,专注于交付有价值的东西,自豪于我们做的事。一个程序员可以使用很 多工具把这些事做得更好,而不是去追逐时尚和流行。
Guido Van Rossum
对不起,我没有那么多水晶球。我CGI被发明了5年后预测过它 :-)
James Gosling
有两个事是我现在最关心的,那就是要对付并行和复杂。
Bjarne Stroustrup
我不知道,我也不愿猜。
Tim Bray
不知道。
Q 5: 如果你有3个月学一个相对较新的技术,你会学什么?
Steve Yegge
我的确有3个月的业余时间,我准备学一下 Dojo (http://dojotoolkit.org) 和高级 AJAX 及 DHTML。我会通过开发一个相当牛的Web应用来学习他们。Dojo 真的酷,并且我确信它会越来越好。
Linus Torvalds
嗯,我真的很爱做 FPGA(可编程芯片),但我部是太忙了而不是坐来来开始学习。我喜爱和硬件打交道:很明显这个原因是因为我最终在做操作系统,因为操作系统(除了编译器)基本上都是在和硬件打交道,但我没有真正地自己去设计和做一个硬件。
David Heinemeier Hansson
Mac 的 Cocoa 编程
Peter Norvig
我想把 Javascript 学得更好,然也当然也想学 flash.
Dave Thomas
如果“新”是对于我来说,那么我会去学钢琴课。
如果“新”是说技术,我猜 我会选择学习某种和为残疾人服务的有关的技术。
Guido Van Rossum
单板滑雪。
James Gosling
搞点有乐趣的东西,我会学习最新的3D渲染技术。我可能会写一个光子映射渲染器。
Bjarne Stroustrup
3个月只有很少的东西你可以学,我觉得你只能参加某个成熟领域的培训。
Tim Bray
安全,加密,数字签名,身份标识,等等。对我来说,从没学过这些东西对我来说是个很大的问题。
Q 6: 你们觉得如何让一些程序员可能有超过其它程序员10倍或100倍的生产力?
Steve Yegge
我想你应该考虑一下为什么不是让所有的程序员都一样牛。托马斯爱迪生有一句关于天才的名言也许会给你一些启示。
Linus Torvalds
我真的不知道,我想,一些人之所以更牛是因为他们可以专注于那些重要的事,而更多的只不过是在应付。那些我所知道的真的很牛的程序员从很年轻的时候就在做事了。
David Heinemeier Hansson
把难题变简单的能力。
Peter Norvig
把整体问题一次性放入大脑的能力。
Dave Thomas
他们关心他们做的事。
Guido Van Rossum
大脑结构基因不同。
James Gosling
他们知道他们要做什么,他们不并不急于仓促行事。他们有他们要做的事的整个蓝图。
Bjarne Stroustrup
首先,缺少足够的职业培训,或基础不够。其次,这些人要即聪明(那种可以把事情想清楚,直达核心的能力),又有经验,并有使用工具的知识。编程需要把理论和实践结合起来 – 并不是使用没有实际业务的知识。
Tim Bray
令人惊讶的思维改变。
Q 7: 什么工具是你的最爱(操作系统,编程/脚本语言,文本编辑器,版本管理,shell,数据库,或其它没它你活不了的工具),为什么不是别的?
Steve Yegge
操作系统: Unix! 我用Linux,cygwin,和 darwin。你无法打败那些高效的工具。每一个程序员都应该学习使用/bin和/usr/bin下的所有命令。
脚本语言:Ruby。我几乎对所有的重要的脚本语言都很熟悉: Perl, Python, Tcl, Lua, Awk, Bash, 和一些我忘了的。但是我太懒了,而Ruby是目前所有脚本语言中最简单的,它应该是天堂制造的。
编程语言:没有一个我喜欢的,我觉得所有的编程语言都很扯。我倾向于Java,因为它很强,可跨平台,有多不错的工具和类库。但是Java未来会进化或是灭亡,Java还没有好到可以永远保持其领先地位。
文本编辑器:Emacs,因为这是迄今最好的编辑器。
版本管理:SVN,Perforce更好一些,但是也很贵。
Shell脚本: Bash, 因为我太懒了去学一个更好的。
数据库: 当然是MySQL,没有之一。
其它:我发现GIMP是无价的,但也是令人恼炎火的。我用这个东西好几年了,但什么也没干,但是我没它活不了。很讽刺吧。Firefox 越来越是我最重要的工具。如果让我去用IE和Safari,我会有严重的窒息感。
注:所有的这些工具 (Unix, Emacs, Firefox, GIMP, MySQL, Bash, SVN, Perforce) 都有一个共同点:他们是可扩展的。例如:他们都有可编程的API。伟大的程序员知道怎么编写他们的工具,而不只是去使用。
Linus Torvalds
实际上,我最终也没有用过几个工具,而我却花了一些时间让这些工具为我工作。最大的事是我自己写了个操作系统,我也自己写了个版本管理系统(git),我用的文本编辑器是 micro-emacs – 最终我也定制和扩展了它。
除了上面三个,其它的东西,我深度关心我的邮件阅读软件,我使用“pine”,并不是因为它是史上最好的邮件阅读软件,因为我习惯了,用它我会有最低限度的大惊小怪。
David Heinemeier Hansson
OS X, TextMate, Ruby, Subversion, MySQL. 这些组合让我很快乐。我希望那些有好的品味的专注于重要的事的工具。
Peter Norvig
我不喜欢那三大操作系统 – Windows, Mac, Linux。我喜欢 Python 和 Lisp. Emacs.
Dave Thomas
在使用Linux10年后我转到Mac平台有两年多了。Mac并不见得有多好,但是它不需要很牛的技术,也不需要经常维护,这让我可以让我更专心得使用它。
我并不是一个单一工具的信仰者,我喜欢换来换去的,这样可以让我有更多的经历。现在,我使用 OSX, Emacs, TextMate, Rails, Ruby, SVN, CVS, Rake, make, xsltproc, TeX, MySQL, Postgres, 还有一堆高效的小工具。没人知道我明年会用什么。
Guido Van Rossum
Unix/Linux, Python, vi+emacs, Firefox.
James Gosling
这些天,我在用 NetBeans. 用它可以干我想干的所有的事,清洁,简单和高效。这是最好的我永远要生活在其中的环境了。
Bjarne Stroustrup
Unix, sam (一个非常简单的文本编辑器), 当然,一个好的C++编译器。
Tim Bray
我喜欢 Unix-like 的操作系统,像 Python 和 Ruby 的动态语言,像Java的静态语言(具体说来是Java API) Emacs, 还有, bash, whatever, NetBeans.
Q 8: 你最喜欢的编程书是什么?
Steve Yegge
大哥,这个问题太难了。也许是”Gödel, Escher, Bach: an Eternal Golden Braid” (作者Hofstadter)?虽然这不是严格意义上的编程的书,如果你要明确意义上的编程书,那么可能是 SICP (mitpress.mit.edu).
Linus Torvalds
嗨。这两天我在读一些小说,或是非计算机读物(老的但是有用的 “The Selfish Gene” 作者 Richard Dawkins)。
如果要问我编程的书,我脑子里只出现了唯 一一本真正的经典的编程的书 Kernighan & Ritchie 的 “The C Programming Language”,因为这本书太牛了,可读性强并且很短。考虚虑一下你想学到这世上一门最重要编程语言,并且它很要很薄,而且还有可读性,这真是一个奇迹。
也就是说,其它我很喜欢的书并不是编程的,而是关于计算机结构和硬件的。那显然是 Patterson & Hennessy 的计算机结构的书,但是我个人也许更喜欢 Crawford & Gelsinger 的 “Programming the 80386?,这是我在开始写Linux时用的书。
相似的原因,我还喜欢 Andrew Tanenbaum 的 “Operating Systems: Design and Implementation”.
David Heinemeier Hansson
我喜欢 Extreme Programming Explained 其摒弃了一般的编程实践,我还喜欢 Patterns of Enterprise Application Architecture 其出众地说明了抽象和具现的平衡。
Peter Norvig
Structure and Interpretation of Computer Programs
Dave Thomas
这关系到你所谓的“最喜欢”,也许我最喜欢的是IBM的 “IBM/360 Principles of Operation.”
Guido Van Rossum
Neil Stephenson的 Quicksilver.
James Gosling
Programming Pearls 作者Jon Bentley.
Bjarne Stroustrup
K&R.
Tim Bray
Bentley的 Programming Pearls
Q 9: 你最喜欢的和编程无关的一本书是什么?
Steve Yegge
只能是一本吗?这不可能。有太多太多我喜欢的书了。
我这个月读过最喜欢的书是 “Stardust” (Neil Gaiman) 和 “The Mind’s I” (Hofstadter/Dennet).
我最喜欢的作者是 Kurt Vonnegut, Jr. 和 Jack Vance.
Linus Torvalds
我在前面说过 Dawkins的 Selfish Gene。在小说方面,有很多很多我enjoy的,但是几乎没有我特别喜欢的一本。我一般不会重读一本书,我的选择总是会变。我可能更喜欢科幻小说, 如:”Stranger in a Strange Land” 作者 Heinlein,这是我青少年时期最喜欢的书,但现在并不是我喜欢的了。
David Heinemeier Hansson
1984, George Orwell.
Guido Van Rossum
Neil Stephenson 的 Quicksilver.
James Gosling
Guns, Germs & Steel 作者 Jared Diamond
Bjarne Stroustrup
我没有固定喜欢的书。目前是 O’Brian 的 Aubrey/Maturin 系列。
Tim Bray
One Day in the Life of Ivan Denisovich
Q 10: 你最喜欢的乐队/演奏家/作曲家?
Steve Yegge
喜欢的风格:古典音乐,动漫原声音乐,电脑游戏音乐
喜欢的作曲家:Rachmaninoff, Chopin, Bach
喜欢的演奏者:David Russell (古典吉它), Sviatoslav Richter (钢琴)
喜欢的动漫音乐: Last Exile, Haibane Renmei
Linus Torvalds
实际上我并不太喜欢音乐,但是当我听音乐的时候,我一般听经典摇滚乐,如: Pink Floyd ,Beatles ,Queen 和 The Who 乐队。
David Heinemeier Hansson
我喜欢很多风格。 Beth Orton, Aimee Mann, Jewel, Lauryn Hill. Actually, 所有的这些都可以归到 Girls with Guitars ;).
Guido Van Rossum
Philip Glass.
James Gosling
我喜欢听民歌: Christine Lavin, Woody Guthrie, Pete Seeger…
Bjarne Stroustrup
乐队: The Dixie Chicks. 作曲家: Beethoven.
Tim Bray
参考资料
https://blog.csdn.net/qq_35975685/article/details/101159643
更多推荐
所有评论(0)