Java/JVM是如何構建的?看看OpenJDK吧!
簡介&歷史
正如有些人已經知道的那樣,從Java7開始,OpenJDK就是Java的參考實現(Reference Implementation)。下圖的時間線可以讓你了解一下OpenJDK的歷史。
如果你想了解從Oracle,Red Hat,etcetera等供應商那里下載得來的JDK或JRE庫,那么可以告訴你,它們都是起源于OpenJDK。每個供應商在此基礎上添加額外的部件。出于安全,專利或其他的考慮,這些額外的添加部分并不公開源碼。
OpenJDK由什么組成?
OpenJDK由許多軟件庫組成,主要有corba,hotspot,jaxp,jaxws,jdk,langtools,以及nashorn。在OpenJDK8和OpenJDK9之間沒有新的軟件庫加入,但有很多改變和結構調整,主要是因為Jigsaw——Java自身的模塊化[2][3][4][5]。
Java語言和平臺是如何構建的?
Java通過引導一個舊版本的Java——例如,Java以其自身為構件建立。舊的組件被組合在一起創建一個新的組件,即成為下一階段的結構單元。關于這種自展的一個很好的例子請參考 Scheme from Scratch或是 Wikipedia [7]。
OpenJDK8使用JDK7編譯和構建,類似地,OpenJDK9 則使用JDK8編譯構建。理論上,OpenJDK8是可以使用從其自身創建的影像編譯的,同理,OpenJDK9也能用OpenJDK9編譯。使用一個叫做循環啟動影像的進程——創建OpenJDK的JDK影像,使用同樣的影像,OpenJDK再一次被編譯。也可以用make命令實現OpenJDK的編譯:
$ make bootcycle-images # Build images twice, second time with newly built JDK
make命令在OpenJDK8和OpenJDK9下都提供了很多設置選項,可以通過命名的方式建立獨立的組件或模塊。如下:
$ make [component-name] | [module-name]
甚至并行運行多個構建過程,如下:
$ make JOBS= # Run parallel make jobs
最后,用install選項安裝上述已構建的組件,如下:
$ make install
一些被神話了的東西
具體來說,OpenJDK或是Hotspot都不完全是用C或C++寫的,代碼庫中相當一部分代碼是良好的OLE(對象連接與嵌入)Java(詳細請看上文的組成圖表)。所以對OpenJDK作出貢獻并不要求你必須是核心硬件開發者。即使是底層的C/C++代碼庫也不是那么讓人望而生畏。下面就是從HotSpot repo的vm/memory/universe.cpp中摘錄出的一個代碼片段——http://hg.openjdk.java.net/jdk6/jdk6/hotspot/raw-file/a541ca8fa0e3/src/share/vm/memory/universe.cpp [10]:
Universe::initialize_heap() if (UseParallelGC) { #ifndef SERIALGC Universe::_collectedHeap = new ParallelScavengeHeap(); #else // SERIALGC fatal("UseParallelGC not supported in this VM."); #endif // SERIALGC } else if (UseG1GC) { #ifndef SERIALGC G1CollectorPolicy* g1p = new G1CollectorPolicy(); G1CollectedHeap* g1h = new G1CollectedHeap(g1p); Universe::_collectedHeap = g1h; #else // SERIALGC fatal("UseG1GC not supported in java kernel vm."); #endif // SERIALGC } else { GenCollectorPolicy* gc_policy; if (UseSerialGC) { gc_policy = new MarkSweepPolicy(); } else if (UseConcMarkSweepGC) { #ifndef SERIALGC if (UseAdaptiveSizePolicy) { gc_policy = new ASConcurrentMarkSweepPolicy(); } else { gc_policy = new ConcurrentMarkSweepPolicy(); } #else // SERIALGC fatal("UseConcMarkSweepGC not supported in this VM."); #endif // SERIALGC } else { // default old generation gc_policy = new MarkSweepPolicy(); } Universe::_collectedHeap = new GenCollectedHeap(gc_policy);
(請注意上述代碼片段可能已在發布在本文后的時間里有所變更了)
從上面的代碼塊中可以明顯看出的是,我們的目的在于展示如何使用預編譯符號創建HotSpot代碼來支持某種類型的GC(GenCollector),比如Serial GC(串行GC)或者Parallel GC(并行GC)。在上述代碼塊中,在一種或多種GC轉換器被觸發之前就已經選擇確定了GC策略的類型了,比如,當UseAdaptiveSizePolicy被激活后,才可以選擇Asynchronous Concurrent Mark and Sweep策略。在Use Serial GC和Use Concurrent Mark Sweep GC二者僅選其一的情況下,被選中的GC策略就是Mark and Sweep策略。除了提供讀起來像英文一樣流暢的格式簡潔的代碼之外,又說了這么多,已經相當清楚了,再多說就很啰嗦了。
更多注釋可以在Adopt OpenJDK Intermediate & Advance experiences [11] 文件夾的Deep Dive Hotspot stuff部分找到。
構建自己的JDK或JRE的步驟
早些時候我們提到JDK和JRE的影像——這些不再是只給Java世界中的大玩家們提供了,你和我都能很輕易的構建這樣的影像。這過程中的步驟已經被簡化了,想快速開始請參看 Adopt OpenJDK Getting Started Kit和 Adopt OpenJDK Intermediate & Advance experiences 文件。想要看更詳細的版本請參看 Adopt OpenJDK home page。要從OpenJDK代碼庫中基本構建一個JDK影像,總結起來就是下面的幾個命令:
(啟動過程被簡化了,忽略了一些命令,訪問上述鏈接可以得到準確的操作步驟)
$ hg clone http://hg.openjdk.java.net/jdk8/jdk8 jdk8 (a)...OpenJDK8
或者
$ hg clone http://hg.openjdk.java.net/jdk9/jdk9 jdk9 (a)...OpenJDK9 $ ./get_sources.sh (b) $ bash configure (c) $ make clean images (d)
(設置的步驟和一些命令省略了,查看上面的鏈接可以查看更詳細的步驟)
解釋一下上述每個步驟的工作:
就像使用克隆版本庫一樣復制OpenJDK每次修改的版本。。。
一旦(a)已經完成,進入新創建的文件夾,執行get_sources.sh命令,等價于一次git fetch命令(抓取)或一次git pull命令(拉取遠程倉庫)。因為步驟(a)中只是降低基礎文件而不是所有文件的成本。
這里運行一個腳本檢查并創建編譯與構建過程所需的配置
步驟(c)完成后,我們就算是從構建好的模塊中完成了一個JDK和JRE影像文件的編譯,構建和創建。
正如你看到的這樣,這些步驟易如反掌,照做就可以建立一個自定義工具或者JDK/JRE影像[步驟a只需要執行一次]。
好處
? 促進Java語言&平臺的發展和改進
? 了解Java語言和平臺的內部構件
? 在達到以上兩點的同時了解OS平臺和其他技術
? 參與到F/OSS項目中
? 保持立于Java/JVM范疇的最新動態之上
? 提供有助于專業且還不能從其他如書籍,訓練,工作實習,大學課程等來源獲得的知識和經驗
? 事業提升
? 個人發展(軟技能及網絡)
貢獻
加入項目Adopt OpenJDK和 Betterrev,向我們提供這些項目中任何與java有關的反饋。可以從加入Adoption Discuss郵件列表和其他OpenJDK相關的郵件列表開始,這些可以讓你了解OpenJDK相關的最新進展和變化。為你看到的任何項目建立分支庫(通過github中的fork repo),然后提交自己的改變(通過github中發起一個Pull Request)。
感謝與支持
Adopt OpenJDK及其隸屬項目由以下組織支持發展:JCP(Openjdk team),JUGs如London Java Community,SouJava和巴西其他的JUGs,歐洲許多的JUGs比如BGJUG (Bulgarian JUG) [18], BeJUG (Belgium JUG)[19],Macedonian JUG [20],還有許多其他的比較小的JUGs。我們希望未來會有更多JUGs組織和個人參與進來。如果你或你的JUG希望參與請聯系我們。
原文鏈接: javacodegeeks 翻譯: ImportNew.com - 范 忠瑞
譯文鏈接: http://www.importnew.com/14610.html