openjdk9u源碼分析一:搭建環(huán)境
搭建環(huán)境可分兩步,
??1. 搭建jdk9u編譯環(huán)境
??2. 搭建jdk9u調試環(huán)境
實驗環(huán)境
?? 1. Mac OS X: 10.13.3.
?? 2. Xcode: 9.2.
?? 3. boot jdk: 1.8.0_162.
?? 4. freetype: 2.9.
?? 5. XQuartz-2.7.11.
?? 6. GDB-8.0.1.
1.搭建jdk9u編譯環(huán)境
- 目標:從官網(wǎng)下載openjdk9u源碼胸墙,正確編譯打包出jdk9u可執(zhí)行文件我注,能夠編譯、運行helloworld程序迟隅。
- 搭建過程:參考https://www.yanshuo.me/p/156958但骨,按照這篇文章能夠正確編譯出可運行的jdk9u。我的環(huán)境和參考鏈接中的基本上一致智袭,除了使用的boot jdk奔缠,我使用的1.8.0_162,而參考文章使用的1.8.0_161补履。
- 結果驗證:
-
編譯后的結果位于源碼根目錄/build下:
目前階段只關注hotspot添坊、images和jdk子目錄,其中hotspot存放jvm的編譯結果箫锤,images存放jdk贬蛙、jrem,doc等產(chǎn)品文件谚攒,jdk存放jdk編譯結果阳准。
-
驗證build出來的jdk版本:
-
Run一個helloworld類:
-
問題總結:
- 網(wǎng)上資料以編譯jdk7、8為主馏臭,總結比較全面的文章請參考https://github.com/ydcun/Java/blob/master/java/src/main/java/com/ydcun/openjdk/jdk8/MAC%E7%BC%96%E8%AF%91OpenJDK8.md野蝇,折騰了半天jdk8的編譯讼稚,把hotspot8u40給搗騰出來了,但在運行hotspot時提示找不到libjvm.dylib:
unable to load native library:dlopen(/Library/Java/JavaVirtualMachines jdk1.7.0_10.jdk/Contents/Home/jre/lib/libjava.dylib, 1):Symbol not found: \_JVM\_SetProtectionDomain Referenced from: /Library/Java/JavaVirtualMachines/jdk1.7.0\_10.jdk/Contents/Home/jre/lib/libjava.dylib Expected in: /Users/Desktop/hotspot-68577993c7db/build/bsd/ bsd\_amd64\_compiler2/fastdebug/libjvm.dylib
這個錯誤應該是沒有編譯jdk8u40的源碼绕沈,只編譯了hotspot的源碼锐想,我用boot jdk7代替了jdk8造成的,但并沒有實際去驗證乍狐≡。看了jdk9u的文章后,里面提到“因為編譯8需要Xcode 4現(xiàn)在Xcode版本已遠高于4了”浅蚪,就放棄了jdk8的編譯藕帜,但現(xiàn)在看,未必是Xcode的版本影響了8的編譯惜傲。
- 在編譯jdk8時洽故,要求安裝XQuartz,我安裝了XQuartz-2.7.11盗誊,但并未能創(chuàng)建這兩個鏈接:
sudo ln -s /usr/X11/include/X11 /usr/include/X11
or
sudo ln -s /usr/local/X11/include/X11 /usr/include/X11
后面編譯成功說明這個問題可以忽略时甚。 - 源碼推薦從http://hg.openjdk.java.net/jdk-updates下載。首先下載根目錄哈踱,然后再分別下載各個子目錄撞秋,下載完后解壓到根目錄下,如下圖所示:
其中嚣鄙,hotspot是JVM的源碼目錄,jdk存放jdk源碼串结,強烈建議在編譯之前先讀common/doc/下的build文件哑子。其他目錄的功能說明大家可網(wǎng)上了解即可,對于編譯過程肌割,基本沒影響卧蜓,如果要運行jdk自帶的測試代碼,需要關注test目錄把敞。 其他兩種下載源碼的方式:使用Mercurial的hg弥奸,openjdk的源碼通過mercurial進行管理。但正如網(wǎng)友@since1986在博文中所述奋早,每次都是下載到一定大小的內容后盛霎,程序自動退出;還有網(wǎng)友修改了get_source.sh腳步耽装,使之自動重連下載愤炸,修改的腳步比較多,而且不保證能成功掉奄,放棄规个。另外衔瓮,git上有上傳的代碼,參見https://github.com/luodaxu/blog-1/blob/master/Java/hotspot-debug-under-osx.md惠昔,但并未驗證赁温。
- 設置環(huán)境變量。
- 設置boot jdk path墅拭。方便起見活玲,下載了jdk7,jdk8兩個版本帜矾,jdk7用于實驗翼虫,8用于工作,如果想直接編譯jdk9屡萤,jdk7也不需要額外安裝珍剑。
export JAVA\_8\_HOME=$(/usr/libexec/java\_home \-v1.8)
export JAVA\_7\_HOME=$(/usr/libexec/java\_home \-v1.7)
alias java7='export JAVA\_HOME=$JAVA\_7\_HOME'
alias java8='export JAVA\_HOME=$JAVA\_8\_HOME'
\# default java8
export JAVA_HOME=$JAVA\_8\_HOME
- 設置編譯參數(shù)。每個參數(shù)上都有說明死陆,大家自行查閱招拙,并可以根據(jù)實驗機器的配置進行調整。本文僅對build和compile的job數(shù)進行了修改措译,編譯一遍通過别凤。
\# 設定語言選項,必須設置
export LANG=C
\# Mac平臺领虹,C編譯器不再是GCC规哪,是clang
export CC=clang
\# 跳過clang的一些嚴格的語法檢查,不然會將N多的警告作為Error
export COMPILER\_WARNINGS\_FATAL=false
\# 鏈接時使用的參數(shù)
export LFLAGS='\-Xlinker \-lstdc++'
\# 是否使用clang
export USE\_CLANG=true
\# 使用64位數(shù)據(jù)模型
export LP64=1
\# 告訴編譯平臺是64位塌衰,不然會按32位來編譯
export ARCH\_DATA\_MODEL=64
\# 允許自動下載依賴
export ALLOW\_DOWNLOADS=true
\# 并行編譯的線程數(shù)诉稍,編譯時間長
export HOTSPOT\_BUILD\_JOBS=8
ALT\_BOOTDIR=$JAVA\_HOME
export ALT\_PARALLEL\_COMPILE\_JOBS=2
\# 是否跳過與先前版本的比較
export SKIP\_COMPARE\_IMAGES=true
\# 是否使用預編譯頭文件,加快編譯速度
export USE\_PRECOMPILED\_HEADER=true
\# 是否使用增量編譯
export INCREMENTAL\_BUILD=true
\# 編譯內容
export BUILD\_LANGTOOLS=true
export BUILD\_JAXP=true
export BUILD\_JAXWS=true
export BUILD\_CORBA=true
export BUILD\_HOTSPOT=true
export BUILD\_JDK=true
\# 編譯版本
export SKIP\_DEBUG\_BUILD=true
export SKIP\_FASTDEBUG\_BUILD=false
export DEBUG\_NAME=debug
\# 避開javaws和瀏覽器Java插件之類的部分的build
export BUILD\_DEPLOY=false
export BUILD\_INSTALL=false
- configure時添加--disable-warnings-as-errors最疆。因為在build hotspot時杯巨,如果出現(xiàn)warnings,編譯過程會認為失敗努酸,實際這些warnings不影響編譯的正確性服爷;也可以在環(huán)境變量中配置:export COMPILER_WARNINGS_FATAL=false,上述配置已包括获诈。
有些jvm源碼需要修改仍源,詳情參見上述參考的鏈接。
jdk9的模塊化等一些新特性不會影響編譯過程舔涎,正如jdk的一位負責人所說镜会,從老版本遷移到jdk9要比之前的升級過程還簡單,至少從編譯jdk源碼的過程來講终抽,jdk9u并未增加額外的工作量戳表。
-
mac下軟件安裝時桶至,可能會遇到verify stuck的情況,參考http://osxdaily.com/2016/07/26/fix-stuck-pkg-verifying-installer-mac-os-x/解決匾旭。
至此镣屹,openjdk9u已經(jīng)編譯成功,并得到一個可用于調試的jvm和jdk价涝。接下來女蜈,使用已構建的程序包,調試一個helloworld的程序色瘩。該過程網(wǎng)上信息比較少伪窖,已有的資料要么jdk版本不一致,要么依賴的軟件包版本不同居兆,要么操作系統(tǒng)不同覆山,對于之前未debug jvm的dev,可能是個痛苦的過程泥栖,但參考下面的內容后簇宽,將會使大家的調試過程變得輕松許多。
搭建jdk9u調試環(huán)境
- 目標:利用已生成的jvm吧享,debug一個java helloworld程序魏割,且能夠debug到jvm的源碼。
- 搭建過程:針對jdk8的調試環(huán)境搭建钢颂,請參考http://blog.csdn.net/tjiyu/article/details/53725247钞它。整個過程可概況為使用GDB(全平臺通用)或LLDB(windows版本正在開發(fā),其他平臺都支持)debug java這個可執(zhí)行文件(GDB殊鞭、LLDB是兩種C须揣、C++程序調試工具,由于hotspot主要采用C++和C實現(xiàn)钱豁,因此要調試hotspot必須要使用C、C++的調試工具疯汁,這些工具可以通過命令行單條執(zhí)行命令牲尺,也可以通過腳步批量執(zhí)行),入?yún)榇龍?zhí)行的java class文件名幌蚊,本文中為Test谤碳。java可執(zhí)行文件啟動一個hotspot實例來執(zhí)行Test class。下面分步驟說明環(huán)境搭建過程溢豆。
- 安裝GDB蜒简。 macOsX high sierra下,Xcode9.2默認使用LLDB漩仙,因此需要安裝GDB搓茬。從GDB官網(wǎng)下載了最新的8.1版本犹赖,并安裝網(wǎng)上的說明進行sign,否則debug時卷仑,eclipse的進度條會一直卡在99%不動峻村。參考https://stackoverflow.com/questions/18423124/please-check-gdb-is-codesigned-see-taskgated8-how-to-get-gdb-installed-w對GDB進行簽名,需要注意:證書類型需要先選擇login方式锡凝,然后再拖拽到system類型下粘昨,否則創(chuàng)建證書會報錯。如下圖所示:
后來驗證的過程說明窜锯,GDB相關的問題是調試環(huán)境安裝過程中最大的一個坑张肾。
* 添加"set startup-with-shell off" >> ~/.gdbinit,.gdbinit是gdb的初始化文件锚扎,也可以在執(zhí)行gdb之前執(zhí)行set startup-with-shell off吞瞪。
* 執(zhí)行csrutil status,查看Debugging Restrictions配置項的值工秩,如果是enabled尸饺,需要更改為disabled。參考https://stackoverflow.com/questions/39702871/gdb-kind-of-doesnt-work-on-macos-sierra/40437725#40437725助币,需要reboot浪听,并在安全模式下執(zhí)行。
* 回退到8.0.1版本眉菱,事實證明8.1.0與OS X 10.13.3兼容性不好迹栓。參見https://gist.github.com/gravitylow/fb595186ce6068537a6e9da6d8b5b96d。在因為GDB拋出"During startup program terminated with signal SIGTRAP, Trace/breakpoint trap."問題時俭缓,曾嘗試使用LLDB進行debug克伊,但LLDB雖然能跑完測試程序,但看不到java程序的輸出华坦,最終還是使用GDB進行調試時看到了java的輸出愿吹。LLDB調試參見https://github.com/luodaxu/blog-1/blob/master/Java/hotspot-debug-under-osx.md,但通過LLDB與GDB的對比惜姐,也找到了GDB不能輸出的原因犁跪,即在gdb捕獲segment invalid異常時,繼續(xù)執(zhí)行歹袁,在hotspot腳步中添加handle SIGSEGV nostop
這一行指令坷衍。后面在介紹hotspot腳步時還會詳細介紹。通過一個C程序驗證GDB已成功安裝条舔。
- 修改Hotspot文件枫耳。該腳步位于./jdk9u-1b1226687b89/build/macosx-x86_64-normal-server-slowdebug/hotspot/variant-server/libjvm/下,它是一個可執(zhí)行的腳步文件孟抗,該文件配置了JDK路徑迁杨、GDB調試器默認的一些參數(shù)钻心,關于該文件的內容可參考《HotSpot實戰(zhàn)》這本書第一章的內容或https://yq.aliyun.com/articles/93753?spm=a2c4e.11153940.blogcont93737.16.6da64d09stvTm2。需要說明的有三點:
* build源碼后仑最,該腳步中已經(jīng)添加了已build的jdk路徑扔役,大家可查看hotspot文件中的這一行: JDK=/Users/Desktop/jdk9u-1b1226687b89/build/macosx-x86_64-normal-server-slowdebug/jdk。
* 腳步中init_gdb()函數(shù)用于配置gdb參數(shù)警医,默認生成的內容中有handle SIGUSR1 nostop noprint亿胸,handle SIGUSR2 nostop noprint這兩行,handle命令的意思是debug過程中预皇,gdb如何處理系統(tǒng)信號侈玄,在后面添加handle SIGSEGV nostop這一行。 - 復制libjvm.dylib文件到hotspot腳步相同目錄下吟温。最初通過“./jdk9u-1b1226687b89/build/macosx-x86_64-normal-server-slowdebug/hotspot/variant-server/libjvm/hotspot -gdb Test”測試時序仙,總是得到一個ERROR“Error: missing
/Users/.../Desktop/jdk9u-1b1226687b89/build/macosx-x86_64-normal-server-slowdebug/hotspot/variant-server/libjvm' JVM at
/Users/Desktop/jdk9u-1b1226687b89/build/macosx-x86_64-normal-server-slowdebug/hotspot/variant-server/libjvm/libjvm.dylib'.
Please install or use the JRE or JDK that contains these missing components.”,該錯誤耽誤了有半天的時間鲁豪,最初依賴搜索引擎潘悼,但網(wǎng)上在mac high sierra下調試hotspot9的資料基本上沒有,只是了解到libjvm就是hotspot的動態(tài)庫爬橡,當時真有些山窮水盡的感覺治唤,于是只能中斷一些時間,休息時糙申,libjvm.dylib missing的錯誤一直在頭腦中浮現(xiàn)宾添,某個時刻突然想到libjvm.dylib文件是不是不在hotspot相同目錄下,于是查找hotspot/variant-server/libjvm/目錄柜裸,發(fā)現(xiàn)該文件在./libjvm/gtest下缕陕,copy一份到hotspot/variant-server/libjvm,即與hotspot文件同目錄下疙挺,測試Test扛邑,得到了期待的結果:
圖中,綠色方框中的為java程序的輸出铐然,紅色框中即為GDB收到的segment fault的信號蔬崩,如果不修改hotspot腳步,GDB會執(zhí)行不下去锦爵。
- 問題總結:
- 使用當前比較新的軟件版本做一些實驗時,網(wǎng)上可參考資料很少奥裸,如果對一些問題領域不太熟悉险掀,可能會花費較多的時間和精力;
- 實驗遇到瓶頸時湾宙,抓住錯誤日志不放樟氢,休息后換個思路再試冈绊;
- 多嘗試不同的思路才可能解決問題;
- 遇到問題請教網(wǎng)上的專家得到響應的情況幾乎為零:(埠啃。
本文知識產(chǎn)權歸創(chuàng)造者所有死宣,復制轉發(fā)發(fā)行需經(jīng)作者同意。