走進JVM之一 本身編譯openjdk源碼

想要深刻了解JVM,就必須瞭解其實現機制。瞭解JVM實現的最好方法即是本身動手編譯JDK。好了,讓咱們開始吧!html

1.  準備工做java

  • 獲取OpenJDK源碼

本次編譯選擇的是OpenJDK7u,官方源碼包:https://jdk7.java.net/source.htmllinux

  • 系統需求

爲了提升效率,儘可能選擇Linux MacOS做爲編譯平臺。本次使用Ubuntu12.04進行編譯。仔細閱讀源碼包中README-builds.html文檔,就能夠構建編譯環境了。bootstrap

   

2.  配置編譯環境vim

  • 編譯依賴

OpenJDK包括虛擬機Hotsport | JDK API | JAXWS | JAXP等。須要各類編譯依賴,包括C++C的編譯環境,編譯JavaJDK(稱爲Bootstrap JDK),還有用於執行java代碼的Ant腳本等等。這些依賴在Linux中均可以經過命令一次安裝完成。oracle

sudo apt-get install build-essential gawk m4 libasound2-dev libcups-dev libxrender-dev xorg-dev xutils-dev x11proto-print-dev binutils libmotif3 libmotif-dev ant

 

固然,也能夠在命令裏面加上openjdk-6-jdk,可是因爲openjdk在後面的編譯中出現了bug,因此仍是建議你們安裝Oracle jdk。注意,bootstrap JDK版本必須在6以上。jvm

  • 環境變量

OpenJDK在編譯時會讀取許多環境變量,因此必須對Linux的環境變量進行配置。使用VIM編輯/etc/profile vim /etc/profile post

具體在profile中添加的環境變量以下性能

export LANG=C

#BootStrap-JDK的安裝路徑,替換爲本身bootstrap-JDK的路徑

export ALT_BOOTDIR=/usr/lib/jvm/java-6-openjdk-i386

#同上,我以前使用的是openjdk編譯的,後面運行hotspot時出現問題替換爲oracleJDK,讀者能夠直接替換爲OracleJDK

export ALT_JDK_IMPORT_PATH=/usr/lib/jvm/java-6-openjdk-i386

#要編譯的內容,讀者能夠根據須要自行選擇

export BUILD_LANGTOOLS=true

#export BUILD_JAXWS=false

#export BUILD_JAXP=false

#export BUILD_CORBA=false

export BUILD_HOTSPOT=true

export BUILD_JDK=true

export SKIP_COMPARE_IMAGES=true

BUILD_DEPLOY=false

BUILD_INSTALL=false

#編譯結果存放的路徑,建議存放在openjdk源碼中build文件夾

export ALT_OUTPUTDIR=/usr/dev/jvm/openjdk/build

export ALLOW_DOWNLOADS=true

#這兩個環境變量須要去掉,否則會出問題

unset JAVA_HOME

unset CLASSPATH

 

添加完成後,進入openjdk源碼路徑,經過make sanity命令來檢查設置是否正確,若是正確,會返回Sanity check passedui

   

3.  開始編譯OpenJDK

  • 使用make命令

openjdk目錄下,輸入make命令,正常狀況下大概須要30分鐘左右,具體速度根據機器性能決定。編譯正常結束後,會出現日誌清單展現內容,如圖

  • 查看編譯結果

進入build/j2sdk-image目錄下,查看整個JDK的編譯結果,運行java –version

4.  運行HotSpot

  • 編輯env.sh

虛擬機的輸出結果存放在build/hotspot/outputdir/linux_i486_compiler2路徑下,如圖

使用VIM編輯product目錄下的env.sh

咱們發現裏面已經有了JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER等環境變量,咱們還須要添加一個LD_LIBRARY_PATH,不然在運行時還會出現問題。

LD_LIBRARY_PATH=.:${JAVA_HOME}/jre/lib/i386/native_threads:${JAVA_HOME}/jre/lib/i386:

export LD_LIBRARY_PATH

 

  • 執行命令啓動JVM

使用以下命令,啓動虛擬機,輸出版本號

. ./env.sh

./gamma –vesion

 

成功結果如圖

至此成功編譯運行OpenJDK7,下面講講過程當中遇到的問題。

   

5.  編譯運行過程當中可能會遇到的問題

  • OpenJDK6.0bug

使用OpenJDK6.0做爲bootstrap JDK的話,在編譯及運行過程當中可能會出現相似於這樣的錯誤,運行./gamma時也可能出現,這類錯誤都屬於OpenJDK-6中的bug

relocation error: /usr/lib/jvm/java-6-openjdk-i386/jre/lib/i386/libjava.so: symbol JVM_FindClassFromCaller, version SUNWprivate_1.1 not defined in file libjvm.so with link time reference

 

網上提供的一種解決方案是經過find –name 'CurrencyData.properties' 找到CurrencyData文件,把文件中的時間所有修改成10年之內。然而我嘗試了這種方法並不能解決問題,因而嘗試把Bootstrap JDKopenjdk-6更換爲OracleJDK6,終於解決問題。

  • 未取消掉JAVA_HOME變量

若是沒有在環境變量中添加unset JAVA_HOMEmake Sanity時會出現如下錯誤

ERROR: Your JAVA_HOME environment variable is set. This will most likely cause the build to fail. Please unset it and start your build again.

Exiting because of the above error(s).

make: *** [post-sanity] Error 1

 

/etc/profile中添加unset JAVA_HOME以解決問題

還有許多在編譯過程當中遇到的問題,在前文中已經進行彌補和完善,相信你們按照這些步驟進行編譯,會省去很多麻煩。

   

6.  總結

經過本身動手編譯OpenJDK-7的源碼,咱們能夠深刻了解JVM的編譯環境以及運行過程。經過解決編譯過程當中遇到的問題,爲後續對JVM的深刻探索打下了良好的基礎。在此基礎上,咱們還能夠經過NetBeansHotspot進行運行和調試,進一步瞭解JVM源碼的結構與細節。

相關文章
相關標籤/搜索