近期Java社区正热议Oracle对Google的侵权诉讼,恰巧前几日在java.net
中看到一篇博文
,文章作者也借此事件表达了Android=Java的观点。由于我对Java移动开发、Android都没太关注过,文章细细读来,有些许进益,译在此处,可能对大家也有帮助。(2010.08.22最后更新)
??? Java社区正忙于讨论Orace针对Google Android平台的专利诉讼。我已在多个场合道出了我的观点,但还是需要一个评论性的文章来重复一下我在每个场合中都作出的相同评论...所以,本博文会将我的想法竹筒倒豆子般地和盘托出。
第八个千禧年问题:Android=Java?
???
几日前,有声明称有研究者已证明了P!=NP,这导致了编程社区中的极大热忱--至少是直到两天前,当第一个评阅者指出了该证据中几处错误时。在我的计算
机科学专业中我已学过这门课,但不能否认地是,我不懂高等数据以至于不能理解这些证明(P=NP?是克雷数学研究所的千禧年问题之一就是一个很好的理
由)。所以,让我们谈谈一个更为简单的等式:Android是否等价于Java?
注意,我说的不是等于
,而是等价
,就如同P=NP那样。
等价的类/字节码格式
??? 在许多层面上,Android = Java是明显正确的。Android应用使用Java语言编写,使用JDK中的javac编译器(或其等价品,如ECJ)进行编译。这就产生了标准的 Java字节码(.class
文件)。然后,这些文件被转化成Android的.dex文件,实际上就是Java类的另一种不同格式的文件罢了。但你也能将GIF图像转化成优质的PNG格式,尽管这两种图像文件的字节码流完全不同,但它们都同样的优秀。
??? 等价的文件格式有大量的实现细节,常常是为了优化。例如,如果我们不需要复杂且不同的跨框架压缩技术,仅仅是满足于低效率的视频流,我们就能避免所有违反MPEGLA视频编码专利的麻烦了。
???
Android设计不同的类文件出于多种动机;但绕开Sun的知识产权肯定是主因。不管怎样,Google不能远离Java。这两种类文件格式非常等价。
它们只是在低层次的数据结构方面不同,但它们的语法是一致的,也存储完全相同的信息。我可以肯定JavaSE或JavaME的VM能很容易地在它的系统类
加载器中加入一个.dex解析器去加载"Android类"。
??? Android SDK依赖
于.java -> .class -> .dex
转
换,这一转换精于细节且是无损的。"无损"是非常重要:虽然GIF=PNG,但有损的JPG文件则不能完全相等--它不能解码出完全相同的信息。如果
JVM和Dalvik真是完全独立的,你就很难写出一个相对简单的工具无妥协的去将编译后的代码从一种形式转换到另一种形式:没有信息丢失;当为了补偿在
一个VM所拥有而在另一个VM却没有的重要特性时;转换后的文件不会变大;当按照一个VM的核心API去实现另一个VM的核心API时,不需要额外的运行
时层。
??? (我知道dx翻译器有多么的复杂。我已看过它的源代码。字节码翻译器很大,它是一个完整的反编译/重编译器,完全使用SSA构建。但这种
翻译只是在理论上比较细微;但在设计上,从Java到Dalvik字节码的影射还是平滑的。栈相对于寄存器架构只是在优化细节方面有所不同;而在关键方
面,如VM层的类型系统,则是一致的。
)
等价的虚拟机
??? 也能很容易的证明Dalvik=JVM。不仅仅是在源代码或字节码格式方面:它们的运行时对应部分也是如此。一旦Dalvik VM加载了一个"Android类",它走起来像Java类,叫起来也像Java类
。如果你懂Java编程(能了解其高级和底层细节),你就懂 Android编程。只是一个学习新API和框架理论的问题罢了。它们是等价的系统。
???
还记得Microsoft的.NET吗?当.NET被介绍出来时,Java社区很快就公开抨击.NET只是Java的翻版。当时我也在那群抨击的人群中,
但现在我知道这么做会更好些。然而.NET是一个庞大的翻版;C# 1.0语言。区别任一语言程序的最方便方法就是风格规范--如,toString()
相对于ToString()
。但在更关键的VM规范方面,Microsoft做了很好的功课。CLR,CLI和核心框架都完全不同于Java,所以我们不能说JVM=CLR。你不能使用一个简单的文件格式转换器工具作用于被编译的Java类,然后将获得信息直接运行在纯粹的.NET运行时环境上。
??? 想要证据吗?只要看看IKVM
。这是一个非常有趣的项目,它能使Java跨越编译运行在.NET环境中,所以你的Java代码可不经过修改运行在CLR之上(或其它同等的.NET运行时环境,如Mono)...但IKVM
并不是
一
个简单的类dx文件转换器。对于任何超过HelloWorld的应用程序,将
Java类及其核心API适配转换到.NET是非常复杂的。每个平台的内在特性,像反射,安全,并发,异常处理,字节码规范,I/O及其它核心API,在
特性上都非常相似,但在细枝末节处则完全不同--强行让IKVM......,则Java代码能运行在.NET
VM上。这也需要一个非常庞大的额外的运行时层,基本上要把全部的OpenJDK源代码适配到JavaSE
API。我追踪IKVM的开发已有多年了--通过阅读极棒的IKVM Blog
--所以我有一个需要作出大量努力的好主意去将Java代码和JavaSE应用适配到.NET。(该工作还没全完成;已完成的部分则常有些性能问题。)
??? (旧有的Visual J++
Visula J#并不是一个简单的Java-.NET解释器。我不会讨论它,但完全可以说Visual J#对Java的兼容要大大劣于哪怕是非常早期的IKVM版本。
)
???
在讨论中我引入了P=NP的例子;有些人可能会引入图灵等价,并说任何图灵完备的平台/语言/VM都是相互等价的。确实如此,但和我们要讨论的问题并不相
干。图灵模型过于通用;如果仅按表面意思来使用它将会摧毁整个软件专利系统(尽管这不是坏事!)。我们需要先在沙盘中勾勒出JVM等价的轮廓,与图灵等价
相比,这更接近于实际需要。依我的观点,无论是细微的二进制格式翻译,甚至于上层的源代码和运行时兼容,都可以明确地将Android置于Java等价的
阵线中。
等价的API与运行时环境
??? Android使用了许多JavaSE
API的子集。这些(来自于Harmony的)API是全新的实现,但它们将JavaSE作为模型。如果不是由于TCK协议的问题,Harmony甚至会
获得JavaSE认证。并不能改变Harmony与JavaSE
API是完全等价的这一事实--这是故意为之,并非偶然。正如JRuby名人Charles Nutter最近写到的:
??? Android支持一个粗糙(但庞大的)Java 1.5类库子集。这个子集足够的大,只需要很少的限制,就能使得如JRuby这般复杂的项目基本上无需修改就可运行在Android上
。
??? 看起来,Dalvik足够接近JVM,它应该就完全遵从大部分JVM的规范,包括完整及非常细节的JMM(Android支持Java风格的线程与并发,直至高级的java.util.concurrent
包)。有太多"Dalvik是一个新的VM"或"Dalvik不能运行Java类"的话(在讨论该问题的90%的博客和论坛中都会发现这样的言论)。
最后的思考
???
本篇并不是关于Oracle针对Google诉讼的是非曲直。我将会忽略(可能会删除)任何跑题的评论(不在Android=Java这一论题之内)。对
于"Android与Java完全不相干"这一无意义的言论我只能表示厌恶;Google和Android的拥趸们必须找到比这更好的论证。
??? (当诉讼的全部细节和结果出来之前,对这一诉讼的将来我保留自己的全部判断。除非你有内部消息(我没有),请不要太天真
。保持冷静
!
我们真的不知道
Oracle或Google的全部意图和计划。自从2007年Google首次发布Android(这导致了JavaME生态系统的极大分裂),虽然
Sun十分愤怒但仍不得不夹着尾巴,我们不知道这幕后的故事。我不会认同任何价值数以十亿计,且由股东控制的公司所持的利己主义的动机。
)
???
我不认为Google创建一个基于Java但偏离Java甚远的平台(如.NET所做的那样)是无竞争力的。在保持对已有Java代码和类库巨大兼容
性,Java人才及Java工具链之间的平衡性的意愿时,Dalvik和Android框架会让你获得尽可能多的好处。
??? 显然,Android=Java不能在双方面都包含进来(不是双射)。每个平台都有一些独一无二的
API,当然,Android是一个完整的操作系统,它包括一个基于Linux的内核,图形和电话栈,等等。我显然只谈及普通的部分:基于Java的用户
空间/应用框架要依赖Java源代码和类(无论是哪种格式的),API(包含数以千计的通用JavaSE
API),以及非常引人注目的类Java的虚拟机。对Android与其它Java平台关系的准确描述可能要使用到版本或测评的概念。我记得一个博客说过
像"Android没有'J'"这样的话。好的,还不晚:我的建议是将Android的名称修改为Java GE(Java Google
Edition)。这就能一劳永逸地消除困惑;-)