微軟當年的 J++ 究竟是什麼?為什麼 Sun 要告它?
目前排名第一的貓殺的答案不錯。我想就所謂「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。
- 它們有很多都以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的研發積累了不少經驗。
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授權協議,不得不說實在是太狹隘了,最終在一定程度上限制了自身的發展。
J++ 是對 Java 的一些修改,或者叫改進,大部分兼容 Java,不過對某些特性並不 100% 支持,當然那些改進都只能在微軟的平台下存在。
而這個思想違背了 Java 的根基,畢竟 Java 的目標是一次編寫到處部署,但如果大家都用微軟的 J++ 去,那麼意味著不同平台移植還是涉及到修改代碼重新編譯,跟 C 成了一樣的性質, Java 的跨平台特性就不存在了,這就意味著 Sun 的 Java 就被釜底抽薪了,一旦這個釜底抽薪完成,這個世界上就沒 Sun/Java 什麼事了。所以可以理解為,為了 Java 的生死存亡,Sun 必須告微軟。
之所以現在 Java 能夠大量的用於伺服器端,很重要的因素還是因為 Sun 保持了 Java 的純凈性,使得它仍然能夠跨平台,要知道伺服器有一部分甚至都不是 Linux,而是私人定製的 Unix,跨平台部署很多時候非常重要,當然最痛恨它的自然是微軟,你們都到 Linux/Unix 裡面部署伺服器了,我微軟的伺服器賣給誰呢?
從微軟的角度,動搖 Java 的根基當然是絕對正確的選擇,而從業界的角度,微軟想把 Java 也變成捆綁到微軟平台的東西,自然也是絕對不正義的。
至於說 Mono 可以用於跨平台,我只能說呵呵。Mono 平台能兼容多少 C# 應用?以那種兼容性敢部署自己的生產系統上去么?還別說 C# .NET 本身是微軟的知識產權,你開源製造一個 C# 一個 .NET 平台微軟可是隨時能告你專利侵權的,微軟雖然口頭上承諾了不告Mono,但這並不等於說微軟無權告Mono,也不等於說微軟授權給Mono做這件事情了。所以如果你想用 Mono 幹活,無論是其兼容性,穩定性,還是法律風險方面,都得不償失。真的喜歡 C# 和 .NET,請直接用微軟平台,當然這也就意味著你與 Linux 的世界無緣了。
雖然 C# .NET 很優秀,可是這個世界上畢竟還有人不願意被綁在微軟的平台上,所以自然會有人抵制它,這,無可厚非。
其實若干年後,Google 的 android 似乎做者類似的事情,重新分裂了 Java,為什麼這次的結果就不同了呢?一方面是時代不同了,另一方面是因為 android 本身開源。而微軟的 .NET 平台不是開源的。即便 Google 消失了,android 本身仍然屬於全人類。而 .NET 卻不是。
微軟的 C# 很牛,.NET 很厲害,技術架構很先進,一切都很好很好很好,但,它只屬於微軟,不是開源的,不屬於全人類,大家不願意選擇一個受到一個商業公司完全控制的技術,就是這樣。
——順便說一下,其實 Sun 也是這樣想的。
補充評論中的觀點:
有人說跨平台很扯,那麼大家今天不談跨平台了,談談一個簡單的問題:如果我就是想在 Linux 平台上選一個開發環境, C# 是首選么?明眼人都應該明白這個道理, mono 至少不是一等公民,是屬於微軟沒把它當親兒子,Linux 社區更沒把它當自己人的存在。
微軟要的是一個微軟作為一等公民的環境,如果你使用 C#,微軟的環境才是首選,Linux 只是需要跨平台適配的時候才勉強用一下的。——但現實是,大家需要一個用 Linux 作為一等公民的環境,需要一個在 Linux 上開發調試,微軟平台是否支持都沒什麼關係的環境。
那麼,為 Linux 平台保留一個商業可用的環境,就顯得尤其重要了。即便它現在的接盤俠是 Oracle 也不能改變這個事實:Java 在 Linux 上的表現,目前大公司可以信賴和依賴它,而一旦依從微軟,這一切將不復存在。Sun搞出個好東西,大家都看好,最大的好處就是一次編寫到處運行。
微軟也看上這玩意兒了,但是不止於用,而是做了很多hack,而且很多都是基於Windows的,當時Wintel聯盟風頭正勁,微軟不能看著Java被Sun把持,要做自己的平台啊,也就不在乎跨平台與否,而是要體現Windows的優勢啊。
但是Java盟主是Sun啊,不甘心Java被篡改,以至於Java像Unix那樣有好多版本,彼此有不兼容的地方。更重要的是不能看著微軟裹挾著許多開發商和開發者專註於J++的開發,造成社群的撕裂。於是就要制止微軟。
這跟今天谷歌制止阿里篡改Android是6一個道理。
反之,你就看看瀏覽器中微軟推出的不兼容特性給前端開發者帶來的麻煩。簡單地說,就是sun授權微軟用java,打算是里利用微軟的知名度,擴大java的使用率。結果發現通過微軟平台開發的java程序,只能在win平台可以用,而在其他平台總有這樣那樣的問題。於是談崩了,就是這樣。
有人知道 sun求微軟捆綁jvm的梗嗎?
「Sun ... 的要求之一,就是微軟必須在Windows中包含有JVM」
ChinaByte
是
Sun 的後繼者 Oracle 連 Google 都告。。。
推薦閱讀:
※優秀的程序員應該掌握多少門編程語言?
※以英語為母語的人寫代碼時是什麼感覺?
※學習彙編語言有什麼好處?
※為什麼蘋果新語言 Swift 的 RC4 運算效能是 Python 的 220 倍?
TAG:微軟(Microsoft) | 編程語言 | 編程 |