目前排名第一的貓殺的答案不錯(cuò)。我想就所謂“Microsoft J++”到底是什么稍微補(bǔ)充幾點(diǎn)。
本文提到的“Sun JVM”主要說(shuō)的是Sun JDK 1.0.2帶的那個(gè)元祖JVM。它在后來(lái)的Sun JDK里被稱為Classic VM,再后來(lái)被HotSpot VM所替代。
當(dāng)時(shí)(Sun JDK 1.0.2)的Java跟現(xiàn)在的Java不可同日而語(yǔ)。別提標(biāo)準(zhǔn)不標(biāo)準(zhǔn),當(dāng)時(shí)的Java毛都沒(méi)有,很多東西所謂“標(biāo)準(zhǔn)”就是“Sun怎么實(shí)現(xiàn)”。
為什么Sun要告微軟?微軟“不乖”,“擅自”擴(kuò)展Java讓它在Windows上變得更好自然是一方面;另一方面Sun對(duì)它的Java合作伙伴們普遍態(tài)度惡劣,非常傲慢和小心眼,這才是更重要的方面。
這方面請(qǐng)參考另一個(gè)問(wèn)題的回答:如果當(dāng)時(shí) Sun 沒(méi)有起訴微軟,而微軟繼續(xù)保持對(duì) Java 的熱情的話,Java 的現(xiàn)狀會(huì)是怎樣? - RednaxelaFX 的回答
另外,想從別的側(cè)面看看當(dāng)年Sun的行為,看看1997年Sun在benchmark上作弊的事情:Sun accused over JIT compiler results
。這還不是Sun第一次做這種事嗯。
關(guān)于控告的過(guò)程,請(qǐng)參考當(dāng)時(shí)的新聞稿:Washingtonpost.com: WashTech -- U.S. v. Microsoft Special Report
Microsoft J++Microsoft J++是外界對(duì)微軟所實(shí)現(xiàn)的Java的開(kāi)發(fā)套件和運(yùn)行時(shí)環(huán)境的統(tǒng)稱。微軟自己其實(shí)并沒(méi)有一個(gè)叫做“Microsoft J++”的產(chǎn)品(或語(yǔ)言)。微軟一直覺(jué)得自己實(shí)現(xiàn)的就是Java語(yǔ)言,只是稍微根據(jù)Windows環(huán)境的需要“增強(qiáng)”了一點(diǎn)而已。
微軟在JDK 1.0.x時(shí)期就獲得了Java的授權(quán),將Java移植到Windows平臺(tái)上。當(dāng)時(shí)的Java真是爛得掉渣,JVM的速度又慢,Java核心庫(kù)的功能又是要啥啥沒(méi)有:
例如說(shuō)能用的容器數(shù)據(jù)結(jié)構(gòu)就只有Vector、Stack(包裝了Vector)、Hashtable(不允許null值)、BitSet,連LinkedList都還沒(méi)有——“誰(shuí)會(huì)要用鏈表呢”。
java.math、java.text、java.sql、java.rmi之類的重要的類庫(kù)都還不存在,locale支持還不存在,圖形庫(kù)只有又慢又不好用的AWT?
嗯對(duì),JDK 1.0.2的時(shí)候連反射都還沒(méi)API,java.lang.reflect也還不存在。Java語(yǔ)言里“接口”這個(gè)語(yǔ)言結(jié)構(gòu)也還不存在。
JNI(Java Native Interface)標(biāo)準(zhǔn)也還不存在。Sun JDK 1.0.2只有一個(gè)非常原始的native interface,而它允許native代碼直接訪問(wèn)Java對(duì)象的內(nèi)部結(jié)構(gòu),既不安全也不可移植。更新信息可以參考當(dāng)時(shí)的文檔:Integrating Native Methods into Java Programs
。
而這個(gè)時(shí)候Windows上已經(jīng)有很多可用的庫(kù),更重要的是:
- 它們有很多都以COM的方式暴露接口
- Java的對(duì)象技術(shù)其實(shí)跟COM有許多重疊之處
于是讓Java能夠更好的利用Windows上已有的資源,真正在Windows上成為一等公民,微軟給Java添加了:
- J/Direct與RNI(Raw Native Interface):用于與native代碼交互
- Java/COM:讓Java能夠使用COM的庫(kù),也讓Java程序能夠暴露出COM接口,便于與其它程序交互。參考這里:Can You Implement COM Components Using Java?
- 委托(delegate):現(xiàn)在Java 8也有l(wèi)ambda,大家都知道這個(gè)是什么了。當(dāng)時(shí)要引入委托主要是為了更好的支持事件模型的回調(diào)。詳情可以參考微軟對(duì)Java委托的專利:Patent WO1999063433A1,以及MSDN的文檔 Delegates in Visual J++ 6.0。微軟當(dāng)時(shí)為Java實(shí)現(xiàn)了委托之后把全套代碼交給了Sun,向Sun申請(qǐng)?zhí)砑釉摴δ艿綐?biāo)準(zhǔn)Java。結(jié)果Sun暴跳如雷急忙批判微軟要分裂Java…
- 還有一大堆的庫(kù)。例如Windows Foundation Classes(WFC)。WFC包裝了Win32和DHTML的圖形組件庫(kù)。Win32的部分跟后來(lái).NET的Windows Forms(WinForms)很像。
- 等等?
微軟版的RNI在Sun版的JNI之前就已發(fā)布,自然就不大愿意再實(shí)現(xiàn)一個(gè)功能非常相似的東西。但微軟決定不在MSJVM里實(shí)現(xiàn)完整的JNI成為了后來(lái)打官司的關(guān)鍵因素之一。
當(dāng)年微軟給Java加了的功能,現(xiàn)在Oracle在一點(diǎn)點(diǎn)給Java加上?
- Java SE 8給Java語(yǔ)言加上了lambda與method reference;
- Java SE 9正在計(jì)劃給Java加上跟J/Direct類似的新的、更方便的native interface
Microsoft Visual J++Visual J++,這是一個(gè)實(shí)際存在的產(chǎn)品的名字。它是一個(gè)用于開(kāi)發(fā)Java應(yīng)用程序的IDE,里面還包含有IE3.0之類的“附屬物”。Visual J++有單獨(dú)發(fā)布的版本,后來(lái)被整合到Visual Studio里發(fā)布。
Microsoft SDK for Java(MSJDK)
這是Sun JDK的微軟版對(duì)應(yīng)物,獨(dú)立于Visual J++免費(fèi)發(fā)布。它包含開(kāi)發(fā)Java應(yīng)用程序所需要的工具套件,例如Java源碼編譯器 jvc(與Sun JDK的javac對(duì)應(yīng)),Java的命令行啟動(dòng)程序 jview (與Sun JRE的java命令對(duì)應(yīng)) ,Java Applet Viewer,Java核心庫(kù),還有Java虛擬機(jī)(MSJVM),等。
有個(gè)有趣的工具叫做 jexegen。顧名思義,它用于為Java程序創(chuàng)建一個(gè)可執(zhí)行程序,把Java程序所需的Class文件打包在生成的exe里。這跟后來(lái).NET Assembly的做法很接近:它是一個(gè)PE文件,不過(guò)啟動(dòng)之后馬上會(huì)去加載MSJVM來(lái)執(zhí)行打包的Class文件。能生成出可執(zhí)行文件讓Java寫出來(lái)的程序能更符合Windows的用戶習(xí)慣。
Microsoft Compiler for Java(jvc)
jvc 是微軟自己實(shí)現(xiàn)的Java源碼編譯器,應(yīng)該是用C++實(shí)現(xiàn)的(求證)。
它的編譯速度非常快,而且編譯時(shí)會(huì)做許多優(yōu)化,編譯出來(lái)的代碼質(zhì)量也比較高。
相比之下,同時(shí)期Sun的javac是用Java實(shí)現(xiàn)的,編譯速度慢一些;雖然也做一定量的優(yōu)化,但沒(méi) jvc 做得深。
jvc 跟當(dāng)時(shí)IBM的 Jikes編譯器
(跟后來(lái)的Jikes RVM不是同一個(gè)東西)地位相似。兩者都用native語(yǔ)言實(shí)現(xiàn)(Jikes用C++),編譯速度都比較快,而且都做比較多優(yōu)化。
同年代同樣用native語(yǔ)言實(shí)現(xiàn)的Java源碼編譯器還有Symantec Café Compiler。
jvc 支持所有標(biāo)準(zhǔn)的Java語(yǔ)言特性,外加支持如delegate、J/Direct之類的微軟擴(kuò)展的特性。
話說(shuō)有個(gè)黑歷史非常搞笑:Sun在控告微軟的jvc不兼容Java規(guī)范的時(shí)候,指責(zé)jvc生成的Class文件通不過(guò)TCK1.1;然后微軟不但說(shuō)明Sun沒(méi)用對(duì)命令(故意打開(kāi)了微軟擴(kuò)展來(lái)測(cè)試),而且進(jìn)一步說(shuō)明Sun的javac其實(shí)也不能完全通過(guò)TCK1.1;關(guān)掉了擴(kuò)展的jvc能通過(guò)的TCK1.1測(cè)試比Sun的javac能通過(guò)更多。
Microsoft Virtual Machine for Java(MSJVM, Microsoft VM, MSVM)
這是微軟實(shí)現(xiàn)的JVM。最初的代碼來(lái)自Sun授權(quán)的Sun元祖JVM,后來(lái)被魔改成Windows上最快的JVM實(shí)現(xiàn)。
IE3 Beta 1的時(shí)候帶的MSJVM還只有解釋器,到IE3 Beta 2就開(kāi)始帶有JIT編譯器了。
MSJVM魔改了Sun JVM核心的每一方面。
- 對(duì)象模型:Sun JVM的對(duì)象模型把“對(duì)象頭”放在了handle里,使“對(duì)象頭”跟對(duì)象實(shí)例數(shù)據(jù)分離到不同的地方了。MSJVM去掉了handle這層間接,于是把對(duì)象頭與對(duì)象實(shí)例數(shù)據(jù)重新“粘”到了一塊。關(guān)于MSJVM的對(duì)象模型,我在另一個(gè)回答里簡(jiǎn)單提了一下:為什么bs虛函數(shù)表的地址(int*)(&bs)與虛函數(shù)地址(int*)*(int*)(&bs) 不是同一個(gè)? - RednaxelaFX 的回答
- 基于直接指針而不是基于handle的引用,訪問(wèn)效率更高。
- GC:準(zhǔn)確式的、分兩代的copying GC。文檔里還專門說(shuō)了沒(méi)使用mark-compact算法。當(dāng)時(shí)的Sun JVM使用的是半保守式、不分代的mark-sweep(帶可選compaction) GC。
- 對(duì)象同步:使用synchronization block而不是老Sun JVM的monitor cache。在對(duì)像頭里包含有一個(gè)指向synchronization block的指針;該指針位于對(duì)象的負(fù)偏移量上。后來(lái)的CLR的對(duì)象頭采用了同樣的布局。在對(duì)象頭里持有這樣的指針大幅減少了查找對(duì)象的monitor的事件。Sun JVM是維護(hù)一個(gè)全局的用hash table實(shí)現(xiàn)的“monitor cache”,把對(duì)象的handle強(qiáng)制轉(zhuǎn)換成int當(dāng)作key去查找這個(gè)cache里的monitor,每次查找都是一個(gè)hash lookup。
- 線程:使用native線程,管理線程用的數(shù)據(jù)結(jié)構(gòu)稍微調(diào)整過(guò)。Sun JVM在Windows上的版本用native thread,而在Solaris上的版本則是使用green thread(JVM自己調(diào)度的用戶級(jí)線程)。
- 添加了JIT編譯器:Sun JVM在JDK 1.0.x的時(shí)候只有個(gè)很簡(jiǎn)陋的JIT編譯器接口,但沒(méi)有發(fā)布JIT編譯器的實(shí)現(xiàn)。MSJVM改造了這個(gè)接口并且提供了一個(gè)當(dāng)時(shí)性能還不錯(cuò)的JIT編譯器實(shí)現(xiàn),而且配合準(zhǔn)確式GC提供必要的信息。
- RNI:在Sun JVM的native interface的基礎(chǔ)上衍生出的一套native interface。
- Java/COM在MSJVM內(nèi)的支持
MSJVM基本沒(méi)怎么改動(dòng)的可能也就是解釋器的核心循環(huán)了。原本在Sun JDK 1.0.2的時(shí)候,Sun JVM的解釋器循環(huán)用純C實(shí)現(xiàn),寫得很直觀但性能很渣;到Sun JDK 1.1.0的時(shí)候改為用匯編實(shí)現(xiàn)
,寫得比較高效,所以也就沒(méi)啥必要魔改這部分,小改動(dòng)然后直接用就好。順帶一提,Sun JDK 1.1.0的JVM的解釋器,在x86上的版本是Intel貢獻(xiàn)給Sun,而不是Sun自己寫的?呃呵呵。
Sun那邊的JIT編譯器有好多黑歷史?Sun JDK 1.0.2自己沒(méi)有帶JIT,不過(guò)有一個(gè)單獨(dú)銷售的產(chǎn)品叫“Java Workshop”,里面帶有一個(gè)能插入Sun JVM的JIT,這個(gè)JIT編譯器叫做“sunwjit”。
可以從這里
下載到描述sunwjit的一篇文章(CompileJava97.pdf,“Compiling Java Just in Time”)。
后來(lái)Sun JDK 1.1.x的時(shí)候開(kāi)始帶JIT發(fā)布了,但卻只在Solaris版上帶有sunwjit,而在Windows版上帶的是Symantec的JIT(“symcjit”)。
據(jù)說(shuō)James Gosling原本自己寫過(guò)一個(gè)JIT編譯器,但是沒(méi)發(fā)布被拋棄了。不知道這跟sunwjit是啥關(guān)系呢。
Microsoft Internet Explorer 3.0(IE3.0)
IE3.0真是當(dāng)年的技術(shù)急先鋒。一方面搭載了JScript來(lái)跟Netscape的JavaScript抗衡,另一方面捆綁了MSJVM以便支持Java。
先寫這么多吧?
=============================================
后話所以說(shuō)當(dāng)時(shí)MSJVM至少可以從三個(gè)地方獲?。篒E3、Visual J++/Visual Studio、MSJDK。MSJVM的許可證也允許第三方程序捆綁它發(fā)布。
順帶一提,根據(jù)Patrick Dussud在Channel 9上的一個(gè)訪談
里提到的,微軟里其實(shí)還有過(guò)一小撮人做過(guò)一個(gè)非正式項(xiàng)目,是寫一個(gè)全新的、“clean-room”(不衍生自Sun的代碼)的JVM原型。這個(gè)項(xiàng)目最后沒(méi)有進(jìn)入產(chǎn)品。或許如果當(dāng)年Sun沒(méi)有禁止微軟開(kāi)發(fā)新版本Java的話,微軟也會(huì)像IBM開(kāi)發(fā)出全新、clean-room的J9 VM一樣有自己獨(dú)立的JVM。
然而歷史沒(méi)有如果。那個(gè)clean-room的JVM原型為后來(lái)的CLR的研發(fā)積累了不少經(jīng)驗(yàn)。
我覺(jué)得現(xiàn)在這樣也挺好的。.NET總算沒(méi)把Java所有的歷史包袱都帶上,CLI(Common Language Infrastructure)的基礎(chǔ)設(shè)計(jì)又比JVM的更進(jìn)步和完善。