百姓大小事,一呼百应!

百姓网 | 百姓知道

通讯通信

微软当年的 J++ 究竟是什么?为什么 Sun 要告它?


2 个回答

  • RednaxelaFX | 2017-10-08 10:15:04

    J++是什么?
    J++是微软的Java实现版本,表达式、关键字、语法规约都和Java一致,符合Java的语言规范,2004年1月停止支持。

    Sun为什么要告微软
    Sun一开始是授权微软可以使用Java的,随后对微软提起了商标侵权的诉讼,因为Sun的商标授权协议里要求实现必须是“兼容的”,才能使用Java的商标。而微软的MSJVM没有通过Java的符合性测试。最终Sun和微软和解,条件是J++只能开发到1.1.4版本,并且停止MSJVM的分发和下载。
    J++的部分技术被回收利用,吸收到了.Net平台,演化成为J#,最终到现在的C#。


    J++与Java的不同点
    • J++没有实现部分Java的特征,如RMI (Remote Method Invocation), JNI (Java Native Interface)
    • J++增加了一些Java没有的特征,如callback,delegate,event,从这时起就已经算是一个不同于Java的新语言了。现在可以在C#里看到这些特征。
    • J++没有遵守Java对操作系统层调用的标准,而是采用了J/Direct框架,提供了一套完全绕过Java类库与API访问OS的机制,能直接调用Win32 API,因而有更好的性能。在现在的.Net框架中,有一套P/Invoke机制与其对应。
    • 使用了MS扩展特征的J++程序不能直接运行在Java SDK上,但有项目能使这些程序跑在开源的JVM上。不过这些扩展并没有被广泛的使用。
    • J++支持ActiveX
    • J++提供了WFC(Windows Foundation Classes)框架,封装了Win 32 API以及DHTML对象模型,主要用于在Windows上开发GUI应用程序。
    可以看到,J++对Java做了大量的改进,这些改进后来都吸收到了.Net平台以及C#语言当中。


    After Math
    从法律和道义的角度来讲,微软违约很不厚道这点毋庸置疑,以下主要是从技术的角度来进行评价,一言以概之,时间证明Sun并没有站在先进生产力的一边。
    最核心的槽点,可能就是J++搞私有API/不跨平台。但这直接带来了性能上的提升,虽然影响了跨平台,但作为一种工程上的trade off,不一定是坏事,想想当年的电脑有多慢吧。现在微软官方的.Net CLR实现出于性能考虑,同样把不少工作推到了平台相关的native代码层上,也并没有影响mono实现跨平台,可见这个槽点根本就不算个事。
    J++可以认为一直延伸到了今天的.Net一系的产品线,所以要评价J++是怎样一种存在,在很大程度上需要把今天的C#/.Net和Java对比。现在Java和C#相比,除了(官方)跨平台,以及因为起步早+成本相对可以较低所以行业应用较多以外,毫无撸点,语言特征方面C#更是甩Java几条街。
    J++增加的语法特征,不少延续到了C#上,用过都知道爽。
    JNI和C# P/Invoke相比,易用性完全不在一个档次上。
    Java至今还鸡肋的泛型,谁用谁蛋碎。
    由于mono项目的存在,使得C#跨平台根本不是问题,唯一影响其广泛在开源社区被采用(如默认在Linux发行版中集成)是因为开源社区普遍不待见微软,并且对微软的CP(Community Promise,微软承诺允许开源社区自由的对包括C#在内的部分微软专利产品、规范编写自己的实现)持保留意见。但这并不影响mono的广泛使用,不少的应用程序、开发框架都采用mono作为脚本引擎,比如Unity3D引擎。
    最近在研究把CoffeeScript编译到CLR上执行,顺便再说下运行时环境,JVM vs CLR。这么多年来,产生了一些编译到Java byte code,然后在JVM上运行的的语言,比如Scala,但并没有证据表明Sun一开始的设计就考虑到了JVM大生态圈的建立。而.Net CLR则提供了一系列相当凶残的方案,比如DLR(Dynamic Language Runtime),编译器的开发者只需要解析出代码的AST(Abstract Syntax Tree),再加上少量的glue code,就能把一种新语言target到.Net上运行,完全无需操心代码生成、代码优化、runtime等等需要花费大量精力的编译器后端环节,并且能在后续.Net升级时,自动获得新的改进(比如更加NB的代码优化算法)。这代表什么?一个开发者甚至不需要把《编译原理》一书读完,翻了前几章能写个词法分析和语法分析,会解决Grammar的Shift-Reduce conflict,就能撸出一个能用于生产的以CLR为目标平台的编译器出来。不管最后结果会如何,从技术的角度而言,微软的解决方案是更有利于开发生态的建立。
    从这些角度来看,J++虽然不能说是完爆Java,青出于蓝四个字还是能提的,进步的态度和力度都是值得称道的。微软在当年受制于Sun的许可协议时,尚且大胆的对Java进行扩展改进,后续衍生的C#/.Net平台的每个新版本的演化力度都不弱,反观Java这么多年来的进展,不免让人呵上一呵。
    和微软现在C#的Community Promise相对比,当年Sun给微软的Java授权协议,不得不说实在是太狭隘了,最终在一定程度上限制了自身的发展。

    本问答由RednaxelaFX提供

  • RednaxelaFX | 2017-10-08 09:52:27

    目前排名第一的猫杀的答案不错。我想就所谓“Microsoft J++”到底是什么稍微补充几点。

    本文提到的“Sun JVM”主要说的是Sun JDK 1.0.2带的那个元祖JVM。它在后来的Sun JDK里被称为Classic VM,再后来被HotSpot VM所替代。
    当时(Sun JDK 1.0.2)的Java跟现在的Java不可同日而语。别提标准不标准,当时的Java毛都没有,很多东西所谓“标准”就是“Sun怎么实现”。

    为什么Sun要告微软?微软“不乖”,“擅自”扩展Java让它在Windows上变得更好自然是一方面;另一方面Sun对它的Java合作伙伴们普遍态度恶劣,非常傲慢和小心眼,这才是更重要的方面。
    这方面请参考另一个问题的回答:如果当时 Sun 没有起诉微软,而微软继续保持对 Java 的热情的话,Java 的现状会是怎样? - RednaxelaFX 的回答
    另外,想从别的侧面看看当年Sun的行为,看看1997年Sun在benchmark上作弊的事情:Sun accused over JIT compiler results。这还不是Sun第一次做这种事嗯。

    关于控告的过程,请参考当时的新闻稿:Washingtonpost.com: WashTech -- U.S. v. Microsoft Special Report

    Microsoft J++

    Microsoft J++是外界对微软所实现的Java的开发套件和运行时环境的统称。微软自己其实并没有一个叫做“Microsoft J++”的产品(或语言)。微软一直觉得自己实现的就是Java语言,只是稍微根据Windows环境的需要“增强”了一点而已。

    微软在JDK 1.0.x时期就获得了Java的授权,将Java移植到Windows平台上。当时的Java真是烂得掉渣,JVM的速度又慢,Java核心库的功能又是要啥啥没有:
    例如说能用的容器数据结构就只有Vector、Stack(包装了Vector)、Hashtable(不允许null值)、BitSet,连LinkedList都还没有——“谁会要用链表呢”。
    java.math、java.text、java.sql、java.rmi之类的重要的类库都还不存在,locale支持还不存在,图形库只有又慢又不好用的AWT⋯
    嗯对,JDK 1.0.2的时候连反射都还没API,java.lang.reflect也还不存在。Java语言里“接口”这个语言结构也还不存在。
    JNI(Java Native Interface)标准也还不存在。Sun JDK 1.0.2只有一个非常原始的native interface,而它允许native代码直接访问Java对象的内部结构,既不安全也不可移植。更新信息可以参考当时的文档:Integrating Native Methods into Java Programs

    而这个时候Windows上已经有很多可用的库,更重要的是:
    • 它们有很多都以COM的方式暴露接口
    • Java的对象技术其实跟COM有许多重叠之处
    于是让Java能够更好的利用Windows上已有的资源,真正在Windows上成为一等公民,微软给Java添加了:
    • J/Direct与RNI(Raw Native Interface):用于与native代码交互
    • Java/COM:让Java能够使用COM的库,也让Java程序能够暴露出COM接口,便于与其它程序交互。参考这里:Can You Implement COM Components Using Java?
    • 委托(delegate):现在Java 8也有lambda,大家都知道这个是什么了。当时要引入委托主要是为了更好的支持事件模型的回调。详情可以参考微软对Java委托的专利:Patent WO1999063433A1,以及MSDN的文档 Delegates in Visual J++ 6.0。微软当时为Java实现了委托之后把全套代码交给了Sun,向Sun申请添加该功能到标准Java。结果Sun暴跳如雷急忙批判微软要分裂Java…
    • 还有一大堆的库。例如Windows Foundation Classes(WFC)。WFC包装了Win32和DHTML的图形组件库。Win32的部分跟后来.NET的Windows Forms(WinForms)很像。
    • 等等⋯

    微软版的RNI在Sun版的JNI之前就已发布,自然就不大愿意再实现一个功能非常相似的东西。但微软决定不在MSJVM里实现完整的JNI成为了后来打官司的关键因素之一。

    当年微软给Java加了的功能,现在Oracle在一点点给Java加上⋯
    • Java SE 8给Java语言加上了lambda与method reference;
    • Java SE 9正在计划给Java加上跟J/Direct类似的新的、更方便的native interface

    Microsoft Visual J++

    Visual J++,这是一个实际存在的产品的名字。它是一个用于开发Java应用程序的IDE,里面还包含有IE3.0之类的“附属物”。Visual J++有单独发布的版本,后来被整合到Visual Studio里发布。

    Microsoft SDK for Java(MSJDK)

    这是Sun JDK的微软版对应物,独立于Visual J++免费发布。它包含开发Java应用程序所需要的工具套件,例如Java源码编译器 jvc(与Sun JDK的javac对应),Java的命令行启动程序 jview (与Sun JRE的java命令对应) ,Java Applet Viewer,Java核心库,还有Java虚拟机(MSJVM),等。

    有个有趣的工具叫做 jexegen。顾名思义,它用于为Java程序创建一个可执行程序,把Java程序所需的Class文件打包在生成的exe里。这跟后来.NET Assembly的做法很接近:它是一个PE文件,不过启动之后马上会去加载MSJVM来执行打包的Class文件。能生成出可执行文件让Java写出来的程序能更符合Windows的用户习惯。

    Microsoft Compiler for Java(jvc)

    jvc 是微软自己实现的Java源码编译器,应该是用C++实现的(求证)。
    它的编译速度非常快,而且编译时会做许多优化,编译出来的代码质量也比较高。
    相比之下,同时期Sun的javac是用Java实现的,编译速度慢一些;虽然也做一定量的优化,但没 jvc 做得深。

    jvc 跟当时IBM的 Jikes编译器(跟后来的Jikes RVM不是同一个东西)地位相似。两者都用native语言实现(Jikes用C++),编译速度都比较快,而且都做比较多优化。
    同年代同样用native语言实现的Java源码编译器还有Symantec Café Compiler。

    jvc 支持所有标准的Java语言特性,外加支持如delegate、J/Direct之类的微软扩展的特性。

    话说有个黑历史非常搞笑:Sun在控告微软的jvc不兼容Java规范的时候,指责jvc生成的Class文件通不过TCK1.1;然后微软不但说明Sun没用对命令(故意打开了微软扩展来测试),而且进一步说明Sun的javac其实也不能完全通过TCK1.1;关掉了扩展的jvc能通过的TCK1.1测试比Sun的javac能通过更多。

    Microsoft Virtual Machine for Java(MSJVM, Microsoft VM, MSVM)

    这是微软实现的JVM。最初的代码来自Sun授权的Sun元祖JVM,后来被魔改成Windows上最快的JVM实现。

    IE3 Beta 1的时候带的MSJVM还只有解释器,到IE3 Beta 2就开始带有JIT编译器了。

    MSJVM魔改了Sun JVM核心的每一方面。
    • 对象模型:Sun JVM的对象模型把“对象头”放在了handle里,使“对象头”跟对象实例数据分离到不同的地方了。MSJVM去掉了handle这层间接,于是把对象头与对象实例数据重新“粘”到了一块。关于MSJVM的对象模型,我在另一个回答里简单提了一下:为什么bs虚函数表的地址(int*)(&bs)与虚函数地址(int*)*(int*)(&bs) 不是同一个? - RednaxelaFX 的回答
    • 基于直接指针而不是基于handle的引用,访问效率更高。
    • GC:准确式的、分两代的copying GC。文档里还专门说了没使用mark-compact算法。当时的Sun JVM使用的是半保守式、不分代的mark-sweep(带可选compaction) GC。
    • 对象同步:使用synchronization block而不是老Sun JVM的monitor cache。在对像头里包含有一个指向synchronization block的指针;该指针位于对象的负偏移量上。后来的CLR的对象头采用了同样的布局。在对象头里持有这样的指针大幅减少了查找对象的monitor的事件。Sun JVM是维护一个全局的用hash table实现的“monitor cache”,把对象的handle强制转换成int当作key去查找这个cache里的monitor,每次查找都是一个hash lookup。
    • 线程:使用native线程,管理线程用的数据结构稍微调整过。Sun JVM在Windows上的版本用native thread,而在Solaris上的版本则是使用green thread(JVM自己调度的用户级线程)。
    • 添加了JIT编译器:Sun JVM在JDK 1.0.x的时候只有个很简陋的JIT编译器接口,但没有发布JIT编译器的实现。MSJVM改造了这个接口并且提供了一个当时性能还不错的JIT编译器实现,而且配合准确式GC提供必要的信息。
    • RNI:在Sun JVM的native interface的基础上衍生出的一套native interface。
    • Java/COM在MSJVM内的支持
    MSJVM基本没怎么改动的可能也就是解释器的核心循环了。原本在Sun JDK 1.0.2的时候,Sun JVM的解释器循环用纯C实现,写得很直观但性能很渣;到Sun JDK 1.1.0的时候改为用汇编实现,写得比较高效,所以也就没啥必要魔改这部分,小改动然后直接用就好。顺带一提,Sun JDK 1.1.0的JVM的解释器,在x86上的版本是Intel贡献给Sun,而不是Sun自己写的⋯呃呵呵。

    Sun那边的JIT编译器有好多黑历史⋯Sun JDK 1.0.2自己没有带JIT,不过有一个单独销售的产品叫“Java Workshop”,里面带有一个能插入Sun JVM的JIT,这个JIT编译器叫做“sunwjit”。
    可以从这里下载到描述sunwjit的一篇文章(CompileJava97.pdf,“Compiling Java Just in Time”)。
    后来Sun JDK 1.1.x的时候开始带JIT发布了,但却只在Solaris版上带有sunwjit,而在Windows版上带的是Symantec的JIT(“symcjit”)。
    据说James Gosling原本自己写过一个JIT编译器,但是没发布被抛弃了。不知道这跟sunwjit是啥关系呢。

    Microsoft Internet Explorer 3.0(IE3.0)

    IE3.0真是当年的技术急先锋。一方面搭载了JScript来跟Netscape的JavaScript抗衡,另一方面捆绑了MSJVM以便支持Java。

    先写这么多吧⋯

    =============================================

    后话

    所以说当时MSJVM至少可以从三个地方获取:IE3、Visual J++/Visual Studio、MSJDK。MSJVM的许可证也允许第三方程序捆绑它发布。

    顺带一提,根据Patrick Dussud在Channel 9上的一个访谈里提到的,微软里其实还有过一小撮人做过一个非正式项目,是写一个全新的、“clean-room”(不衍生自Sun的代码)的JVM原型。这个项目最后没有进入产品。或许如果当年Sun没有禁止微软开发新版本Java的话,微软也会像IBM开发出全新、clean-room的J9 VM一样有自己独立的JVM。
    然而历史没有如果。那个clean-room的JVM原型为后来的CLR的研发积累了不少经验。

    我觉得现在这样也挺好的。.NET总算没把Java所有的历史包袱都带上,CLI(Common Language Infrastructure)的基础设计又比JVM的更进步和完善。

    本问答由RednaxelaFX提供

* 本站部分内容来源自网络,仅作分享之用,侵删。