30 秒看懂
James Gosling 对 Lex Fridman 说,Java 并非为了语言革命本身而生。在目睹消费电子公司糟糕地重复发明网络功能、C 程序员不断泄漏内存之后,他想做的是让业界最常见的安全漏洞根本无法被写出来。谈话中他还讲到一台 300 伏的井字棋机器、用一个月的夜晚赶出的 Unix 版 Emacs,以及他为什么宁愿生活在《星际迷航》里,也不愿生活在《银翼杀手》里。
- 1Gosling 坚持一种许多队友都觉得不健康的写代码风格:代码非常紧凑,几乎不留空白,一个函数刚好能装进一屏,因为滚动本身就是一种遗忘。
- 2他至今仍记得第一台机器的参数:4K 内存、12 位字长,时钟约为三分之一兆赫。而现代机器大约快了一万倍。
- 3少年时代搞电子,靠的是从垃圾堆里翻出来的继电器和拼凑的电源。他的井字棋机器跑在 300 伏电压下,所有连接都没有做绝缘。
- 4他对老编辑器的最佳评语是:用 TECO,就等于闭着眼睛用 Emacs。
- 5他用 C 写了 Unix 版 Emacs,因为 C 是 Unix 上唯一真正能用的语言;一两个月内,它就能编辑自己的源代码了。
- 62020 年,一项对 Chrome 高危漏洞的研究发现,其中 60% 到 70% 仍然是“愚蠢的指针把戏”。而那时距离 Java 启动、要让这类错误无法被写出来,已经过去了三十年。
按章节阅读完整文稿
二的平方根:摧毁了一种信仰的数字
Lex Fridman 一开场就提到一则传闻:二的平方根是 Gosling 最喜欢的无理数。Gosling 不知道这说法是从哪里来的。他记得的是,少年时曾狂读《好奇与有趣数字词典》,几乎能背下来;还有一个习惯,就是让支票和信用卡的总额凑出一个有趣的数字。
Lex 坚持要他讲一个关于二的平方根的故事,他便讲了一个更好的。毕达哥拉斯学派相信,每个量都能写成两个整数之比,直到一个证明表明√2 做不到。从这个意义上说,它是唯一一个摧毁过一种信仰的数字。他说,完美原来有一个不完美的定义。
哥德尔的不完备定理在二十世纪再次毁掉了这个梦想。Gosling 从中得出的结论,与通常那种“有些事情永远无法知道”的说法不同。在他看来,人们想要的是真或假。如果允许出现第三种状态,比如真、假,或者说不一定,生活就会好过很多。这段插话也是理解他设计思路的一把钥匙:他想要超越二元对立的第三层,而且无法容忍对程序实际做什么含糊其辞。
他把程序看作机器,所以它必须能装进一屏
Gosling 说,从理论计算机科学中留下来的,是一种习惯:看着一段代码,在自己心里证明它是对的。这让他和几乎每一个他加入过的团队,在代码排版上都有分歧。软件工程师对换行和大括号非常计较。他的做法恰恰相反:风格非常紧凑,尽量压缩空白,这样他就能一次看到整个函数,而不必滚动着去记住前面的内容。
团队里曾经发生过他所说的“干预”。人们提早到场,坐下来等他,然后说:“James,关于你的编码风格……”按他自己的说法,他是个不太像程序员的人:他不擅长用语言思考,读东西慢,大多数人会称他为视觉型思考者。
被问到想到一个程序时脑子里会看到什么,他的回答是:画面。纸上的代码会变成某种机器,这个连着那个,齿轮相互咬合。他看不到字母构成的词法结构。这就是为什么一个函数必须待在一个地方:输入、输出,以及它在做什么,必须一起从纸面上跳出来。就他而言,抽象不是一种语言行为。
第一台电脑是被冷落的 PDP-8,第一批硬件跑在 300 伏电压下
他学的第一台机器是卡尔加里大学的一台 PDP-8。他至今还记得参数:4K 内存、12 位字长,时钟约为三分之一兆赫。他估算,今天的机器大约快了一万倍。它算不上超级计算机,只是一台早期的小型机,便宜到大学实验室可能买得起。在某个网络项目不再使用它之后,它被搁在计算中心的一个角落里。他注意到它闲在那里,就开始折腾,也没有人反对。
交互界面是一台 Model 33 电传打字机,配纸带;当时还没有显示器。它是第一台用集成电路制造的计算机,那时一块硅片上只能集成十来个晶体管,而不是今天的数十亿个。Lex 问他是否在指尖上感受到了摩尔定律。Gosling 不接受这种浪漫化的说法:它就是个玩具。重要的是经济因素。做实体东西需要木料、导线和开关,而这些都要花钱。软件让他可以免费构造任意复杂的东西。
他很穷,电子项目的材料来自翻垃圾堆。最大的宝贝是从一个电话局交换中心后面丢弃的继电器机架,他用它做成了一台井字棋机器。继电器需要特定的电压,他没有合适的电源,就用废旧电视机拼凑了一个,“不对,但能用”。继电器跑在 300 伏电压下,所有连接都没有密封。Lex 对他竟然没出事感到惊讶。Gosling 说原因有很多,其中包括他少年时发现铝热剂其实很容易做出来。
在组装之前,那台 PDP-8 上用的语言是 FOCAL-5,一种精简版的 Fortran。他写过二十一点、纸牌接龙,还有他最喜欢的程序:在电传打字机上用字符敲出的函数与数据图。他从来没有觉得语言本身有多美,关心的是你能用它做什么。语法之争至今仍让他觉得无聊。等到别人肯雇他的时候,工作主要是在 CDC 6400 这类机器上写汇编和 Fortran。CDC 6400 是一台早期超级计算机,其算力还不如他的手机。
Lisp 很好,就是括号太多;在它之上的是 Simula
Lex 给出了那个常见的共识:Lisp 是有史以来最伟大的语言。Gosling 把它放进了自己的名单,却不肯把它排第一。他说,最让人不喜欢的,是括号太多。在这些括号下面,藏着一种有趣的语言结构,他一直怀疑,某个更友好的 Lisp 就藏在某处,只是他从来没有花时间去找它。
在他眼里,比 Lisp 更高一层的是 Simula。几乎没有人用过它,但有很多人受到它的影响。它谈不上是早期的函数式语言,却是第一门面向对象的编程语言,对象与语言在这里汇合,协程(coroutine)也是在这里第一次作为语言特性出现的。Simula 67 诞生于 1967 年。
协程像是没有真正并发的线程,所以你可以绕开加锁的噩梦。除非你陷入信号量和锁,否则也真正用不上多个核心。它的好处是一种思维模型:你可以像在写多线程程序那样思考,并以不同方式对待一类问题。对象加上一种看起来像并行的顺序写法,这个组合在他的排名中,排在了大家都想让他推上王座的那门语言之上。
Emacs 就是睁着眼睛用的 TECO;它用 C 来写,因为 Unix 上没有别的选择
大约在 1985 或 1986 年,Gosling 已经用了几年 Unix。日常编辑用的工具,他形容为 vi 的前身:如果输入设备是电传打字机,它还算不错,而且比 TECO 更人性化。TECO(Text Editor and Corrector,校正器)是曾在 MIT 的大部分环境中占主导地位的编辑器。它的宏语言晦涩到,写在纸上的程序看起来像随机字符,他说它比 LaTeX 糟糕得多。它是为高速盲打优化的:几乎每个键都是一个命令,配合 Shift 和 Control,一个键可能代表两三种命令。
最初的 Emacs,名字取自编辑器宏(Editor MACroS),在 MIT 是一堆 TECO 宏。后来的实现在代码库上完全不同,但哲学一脉相承。Emacs 增加的,是让你能以与文档一致的形式看到自己正在编辑的内容。Gosling 最令人印象深刻的类比是:用 TECO,就是闭着眼睛用 Emacs。你得在脑子里维持一幅图景,知道光标正停在两个字母之间,然后发出命令。
他第一次真正用的 Emacs 不是用 C 写的。在 Multics 上做 Pascal 编译器的暑期工作,让他在三个月的高强度投入中用上了 Bernard Greenberg 的 Maclisp Emacs,他几乎就生活在里面。回到卡内基梅隆大学,校园里什么都有,唯独 Unix 上没有 Emacs。他用 C 写了一个,因为 C 是 Unix 上唯一能用的语言。一两个月之内,它就好到能编辑它自己。然后它占领了整个大学,并蔓延到 ARPANET 上,因为 Unix 正在占领研究界,而 Emacs 是当时最好的编辑器。
有一段时间,他在 ARPANET 上所有非军用主机都有登录账号。人们会写信请他帮忙安装,他也乐于帮忙。他说,那是个没人在乎安全的年代。
ARPANET 早就是社交媒体,有线电视公司却讨厌接下来的变化
他能想象今天的互联网吗?他说,有一部分几乎没怎么变。在卡内基梅隆,社交生活以 ARPANET 为中心。那时没有手机,人们坐在终端前打字。电子邮件和一行行的留言,实际上就是聊天,只是不叫这个名字;人们用它约午饭,也用它约会。从 1980 年代初到中期,他就已经身处类似社交媒体的环境里。等到消费级互联网爆发时,他的反应是:有什么了不起的?规模确实惊人,但它的根本面貌几乎没有动。
真正变化的是与既得利益集团的斗争。有线电视公司、广播公司和电话公司从骨子里讨厌互联网,因为它无法被它们控制。大多数有线电视的员工认为,自己的工作是把节目送到付费的用户手中。层级往上爬,看法就变了:真正的生意一直是把用户的眼球卖给广告商。Gosling 与有线电视公司有过几次冲突,那种分层的格局在冲突中表现得很清楚:底层服务用户,顶层则把用户卖出去。
1990 年代初,Sun 的一个团队写了一份提案,要点是:互联网技术让任何人都能成为出版者,比如给父母看的家庭录像、孩子的作文,还有杂货店或餐馆对外发布的信息。他们觉得这会很棒。有线电视公司的反应是否定的,因为那样一来它们就要倒闭了。它们看不到一条不去维护旧金字塔结构的营收路径。
柯达看得见曲线交叉,却扛不住那一下冲击
Gosling 说,对大公司的教训是:当你在一个即将消亡的模式上赚着大把的钱时,会发生什么。Sun 的大客户柯达,是他从内部了解的故事。柯达有一个相当大的数码相机与数码成像部门。他们能画出趋势线:胶片今天还更好,数码在快速进步,而两条线的交叉会让胶片业务崩溃。他们完全知道这一点。直到撞墙之前,他们仍在赚大钱,而账面上从来没有明确指出应该带头冲锋。
跨越鸿沟,意味着先要经历一段低谷:营收下滑,连续几个季度的难看数字。上市公司的规则很简单:首席执行官绝对不能让一个季度出现重大损失。特斯拉和亚马逊在早期可以暂时不理会股市。他们优化的是让顾客满意,这有时反而与利润底线相对立。亚马逊亏损运营,是把它当作对未来的投资。这只有在耐心资本站在一位富有魅力的领袖身后时才行得通,而这位领袖手里持有大量股票,可以直接把事情做成。
贝索斯既有远见,也有执行这一远见的能力。很多人都有远见,但 Gosling 说,平均而言,这些远见是愚蠢的。硅谷的失败率很高,而且往往取决于时机和运气,不只是蠢主意。他把特斯拉的 Model X 称为一个傻乎乎的举动,从工程角度看,那种鹰翼车门完全是一场闹剧。但它们也象征着领导力:如果你碰巧做了一件蠢事,那就干脆蠢到底,全力投入。
乔布斯越过了那条线,而“聪明工作,而不是拼命工作”通常行不通
Gosling 说,乔布斯是个类似的人物:远见很强,非常聪明,他的聪明与其说在技术上,不如说在人与物的关系上。他也是个混蛋。Fridman 问,这是特性还是缺陷?乔布斯对人很苛刻,你可以把它说成是不必要的残酷,也可以说成是逼人达到他的愿景。结果讲述了另一个故事:人们常常做出了自己职业生涯中最好的工作。Gosling 与乔布斯面谈过几次,私下里也喜欢他,但从来没能为他工作。
乔布斯会大吼大叫,也会骂人。Gosling 认为没有必要这样做。督促人们追求卓越是一回事,过了头又是另一回事,而他认为乔布斯越过了那条线。他厌恶的,是后来笼罩当代硅谷的那套神话:由彻头彻尾的混蛋带领的高飞成功,以及一种货物崇拜式的观念,认为想成功就得做混蛋。他说,这讲不通。他认识很多成功人士并不是混蛋。他们往往不在公众视野里,因为混蛋做的事情会上新闻。
Fridman 从另一面提出异议。他担心硅谷对努力工作有抵触,并把“聪明工作,而不是拼命工作”听成了懒惰的借口。找到一个简短的程序,仍然需要大量笨功夫。Gosling 同意,并进一步说:聪明和拼命是“和”的关系,不是二选一。那些劝人聪明工作而不要拼命的人,几乎总是失败。在混蛋问题上,他举谷歌作为反例:在他看来,Larry Page、Sergey Brin 和 Sundar Pichai 都相当好相处,公司文化是大家非常非常拼命地工作。
开源是一种建立社区的方式,不是一项清贫的誓言
Fridman 问了一个尖锐的问题:Gosling 在 Java 之外的一些最好的工作,没有像它们本可能的那样流行,部分原因在于许可证。总体而言,Gosling 是开源的大力支持者:社区、协作、更快的开发。但当开源变成一种宗教,宣称所有东西都必须开源时,他就觉得有点怪。他说,这种极端版本最终会要求所有软件工程师都发下清贫的誓言,仿佛有钱或创办公司是不道德的。
他有一部分理解这种冲动。一项专利可能在你半醒着躺在床上时突然闪现,然后带来数十亿美元;运气终究是运气,直到它膨胀成看起来像剥削的东西。他举了每天要花一百美元的药物为例。他真正在意的测试则更窄:当某样东西不是开源的,并且因此变成了一个更差的产品,这件事让他难受。
Fridman 用的是 Emacs,还为没用 Gosling 的 Emacs 而道歉。Gosling 说,Linux 上的默认版本,经过一段奇怪的过程,最初就是他写的那个。研究生最后几年,他很清楚,自己要么永远做 Emacs 先生,要么毕业,两者不可兼得。如果 Emacs 发展成一条文字处理产品线,他本可能变得富有。他一直做着在财务上并不最优的决定,因为他不想要那种生活。他请 ARPANET 上认识的所有人接手代码,但他们都有正经工作。一个新泽西车库里的两个人,外加一条狗,如果能收费,就会接手。他的条件是,它对大学和学校必须保持免费。这让一些人很不高兴。
在 Gosling 的描述中,他与 Richard Stallman 的分歧,是“信息必须自由”的极端形式:凡是靠制作电影或软件谋生的人,都必须发清贫的誓言。他不想变得极其富有,也确实没有;但他需要养活孩子。闭源却导致官僚主义膨胀、伤害产品,也让他难过。他尊重的中间路线是服务和支持。《萨班斯-奥克斯利法案》和会计规则甚至会促使企业为自己依赖的软件购买支持合同。这是一门正当的生意,和 Oracle 这类“真正贪婪”的厂商收取的费用不是一回事。赢家通吃的商业模式对他也行不通。
Java 是在一个不断重复造出指针 bug 的世界中被逼出来的
大约 1990 年,Sun 的一个团队担心计算机行业没有注意到外部正在发生的事。电梯、机车、工厂过程控制、音视频设备,以及蜂窝电话的早期雏形,里面都有处理器,而且数量比传统计算机业务大得多。C 和 C++ 当时完全统治着那个世界。他们的直觉是:外面正在发生某种事情,他们需要先理解它,至于是否需要一门新语言,还是后话。他们中的一些人做了史诗般的长途旅行:在日本拜访东芝、夏普、三菱、索尼;在韩国拜访三星;在欧洲拜访飞利浦、西门子和汤姆逊。Sun 的名字为他们打开了不少大门。
最让他们吃惊的是,消费电子公司在重新发明计算机网络,并重复二十年前的灾难。Gosling 看一眼设计,就能说出二十五件会彻底失败的事情。但他们从这些公司学到的东西更重要。这些公司把与客户的关系视为神圣,不愿为了性能牺牲可靠性。计算机行业却愿意。Cray 用牛顿式近似让除法变快,但商的最低几位实际上是随机数。Gosling 说,这好比把面包放进烤面包机,你总不希望房子因此烧起来,所以最低位必须钉牢。
他们决定用朴素的方式理解市场:做一个原型,一个家用电子设备的控制系统,比如电视机和录像机。他们用 C 和 C++ 来写,标准做法却成了阻碍。一位搞商业计划的同事,一个 MBA,不断提出外行问题,逼着工程师们重新审视安全、保障和裸指针的问题。到 1990 年代初,人们已经清楚,安全漏洞的头号来源是指针错误,占了 50%、60%、70%,其中绝大多数是缓冲区溢出。他们必须让这件事变得不可能。Gosling 指出,2020 年对 Chrome(一个巨大的 C++ 代码库)漏洞的一项检查发现,其中 60% 到 70% 仍然是“愚蠢的指针把戏”。三十年过去了。他说,人会拍着额头,只想哭。
指针只是一个触发点,而不是整个设计的全部。并发很重要,因为等待一个面向用户的设备,简直是致命的。故障恢复也很重要,还有内存泄漏,以及泄漏的邪恶孪生兄弟:内存被释放了却仍在使用。他花了不可思议的时间去追查神秘的指针错误,大概占他做开发者时间的三分之二。这些错误是统计性的,概率只有百万分之一,但在每秒十亿次操作下,它们总会发生。他对立即、明显地失败有一种近乎宗教般的执着。采用 Java 的团队往往能更快达到生产级质量,即使第一版演示并不更快。面向对象的接口也是一种人际协作上的设计:他让偷偷走后门变得很难,所以正确的做法是走到作者面前,直接改接口。在课程项目中,你同时拥有两边;在跨组织的情况下,清晰能救命。
JVM 起初是一个采购问题,加上一个偷懒的编译器技巧
Fridman 称虚拟机是编程史上最美的想法之一。Gosling 说,JVM 经过精心设计,可以有不止一种读法。大多数人忽略的一种读法是:你可以把它看成是以逆波兰记号对抽象语法树所做的编码。公开的那种读法则是:一套可以翻译到实体机器上的抽象机器指令集。这很重要,原因在于 1990 年代初他与采购部门的几次交谈。
金属板材、齿轮、电容器和电阻都有多家供应商。CPU 则是专有的,而且各不相同。选了英特尔,你就永远是英特尔的客户,因为软件和那颗芯片焊死在了一起。C 语言尤其糟糕,它会把字长、字节序和浮点行为泄漏进程序里。采购人员被逼疯了:他们必须在第一行软件写出来之前,就做出不可逆转的供应商决定。换代也没有更仁慈。Sun 从摩托罗拉 68010 换到 68020,其中的差异耗掉了 Gosling 整整一年的时间;他成了处理最棘手的那些指令缓存意外的负责人。
顿悟来自研究生院的一份暑期工作。他的导师是 Raj Reddy 和 Bob Sproull。系里有几台 Three Rivers PERQ 工作站,其指令集竟然就是 UCSD Pascal 的 p-code,因为那家硬件公司想尽可能少地做软件。当他们需要在 VAX 上运行那套软件时,Reddy 让他做一次翻译。Gosling 注意到,他可以把 p-code 改写成 VAX 汇编,结果比 C 编译器生成的代码质量更高。他觉得这是个投机取巧的小把戏,因为他偷懒;但它管用。没有人想把它当作论文题目。多年后,面对一大堆微处理器,他想到可以在那个 p-code 空间里做多种翻译器,还和同样使用字节码的 Smalltalk 人士交流,并同时保留了解释器(简单)和编译器(快速)。他的不少好主意都来自懒惰,而有些人最蠢的主意,恰恰是因为懒得不够彻底。
同样的本能后来变成了算术上的一套信条。整数就是二进制补码,就这样定了,不是反码,也不是十进制。浮点数一直是一团乱麻:在 CDC 上能跑的数值库,在 IBM 上未必能跑。IEEE 754 大体上已经普及,只剩下一些顽固的少数派。Gosling 想要的是能够说清楚“二加二”到底意味着什么。最大的争执来自英特尔,它打着优化的旗号,在舍入上搞出了怪异的做法,在超越函数上搞出了更怪的东西。他们在正弦和余弦的范围归约中,用了一个稍有偏差的圆周率值。
Android 越了本不必越的线;他宁愿生活在《星际迷航》里
谈到 Android,Gosling 必须给出一个简短的回答,而他显然讨厌这么做。他对他们做成这件事是高兴的。Java 早已在手机上运行了多年,而且运行得很好。问题在于他们做事的方式。主导这项工作的 Andy Rubin 越过了很多界限,而这些越界行为最终膨胀成了巨大的官司。这些本来没有必要。不越线会便宜得多。Fridman 问,是否没有人预料到它会成功。Gosling 后来认为,Rubin 做什么都无关紧要,它注定会炸开。他开始把 Rubin 想成一个制造炸弹的人。世界上最好的一些东西,正是从这种爆炸性的东西中来的;而最糟的东西也是。
骄傲比 Android 更早。在 Android 到来之前,Java 已经在数十亿部手机里了。他对那些采用 Java 的智能卡标准同样引以为豪,认为参与其中的每个人都做得很好。你口袋里的 SIM 卡运行的就是 Java。在他看来,这就是那些不那么显眼的“数十亿”。
被问到希望五百年后人们怎样写他,他说:人们不怕纵身一跃,去相信某件事。他有一段奇怪的经历,做过许多怪事,而且大多数效果还不错。有些最怪的部分恰恰是最酷的;他做过的事情有一大半以失败告终,这有时真的很让人恼火。但你还是会继续做下去。即使是失败,也会教你一些东西。给年轻工程师的建议是:不要害怕风险。蠢事做一次,甚至做两次,也没关系。前一两次可以被原谅,第三次、第四次,就不那么容易被原谅了。
早年他就习惯把每个技术决定放进科幻框架里来想:你是在造《银翼杀手》,还是《星际迷航》?你更愿意生活在哪个未来?毫不犹豫,是《星际迷航》。Fridman 把这个框架套用到 AI 上:他最喜欢的系统是《星际迷航》里的 Data(数据),最不喜欢的是天网(Skynet)。Gosling 表示同意,Fridman 也就此结束了这个话题。Gosling 在节目结尾说,生活里最难的事情之一,就是做选择。从被冷落的 PDP-8,到 300 伏的继电器,到一个月做成的 Emacs,再到一台讨厌指针错误的虚拟机,贯穿其中的其实是同一个选择:先让世界小到能看清,然后纵身一跃。
同频道的其他文章
3:36:56EN → 简体中文
5:15:51EN → 简体中文
3:12:58EN → 简体中文
3:46:18EN → 简体中文
3:51:47EN → 简体中文
2:53:42EN → 简体中文