最近在看synchronized 鎖優化方面的內容,有些地方看起來不是很方便,干脆就編譯個源碼來看看。
在windows上編譯
由于自己常用的電腦操作系統是win10,所以最開始是想要在win10上編譯的,但是一來網上文章太少,二來在windows上編譯確實麻煩太多了(windows可以參考深入理解JVM虛擬機這本書),故放棄了。
MAC環境
準備
獲取源碼
OpenJDK源碼使用Mercurial管理,如果通過版本庫下載,則需要安裝Mercurial,我們借助homebrew包管理器來安裝
brew install mercurial
如果你的電腦沒有安裝homebrew,那么可以使用下面的命令來安裝
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
安裝完成后使用以下命令clone源代碼
cd ~/jvm
hg clone https://hg.openjdk.java.net/jdk/jdk12
命令運行之后,openjdk的源碼并沒有下載下來
由于我并沒有使用hg的方式,關于這部分可以參考閃電俠的文章http://www.lxweimin.com/p/ee7e9176632c
當然我非常不建議你使用Mercurial的方式下載,這種方式不久要等很久,而且還需要科學上網才穩妥。我墻裂推薦你直接通過頁面下載OpenJdk12源碼壓縮包)
比如我下載的是gz格式的文件(選擇什么格式并不重要)。
如果你使用的Chrome,那么可以開啟多線程下載,速度會有一個很明顯的提升。
Bootstrap JDK
因為OpenJDK的各個組成部分有的是使用C++編寫的,有的是使用Java編寫的,因此編譯這些Java代碼需要使用到一個可用的JDK,官方稱這個JDK為“Bootstrap JDK",一般來說只需要比編譯的JDK第一個版本,這里采用OpenJDK11,可以通過這個網址 https://jdk.java.net/archive/ 下載
記住一定要下載一個適合Mac平臺的OpenJDK11。
我使用的Bootstrap JDK版本如下
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
安裝依賴
# 用于生成shell腳本的工具,可以使軟件包在不同的系統下都可以編譯
brew install autoconf
# 字體引擎
brew install freetype
XCode 和 Command Line Tools for Xcode
這兩個SDK提供了OpenJDK所需的編譯器以及Makefile中用到的外部命令。一般電腦上都自帶安裝了。
網上很多編譯出錯都是因為XCode版本問題,導致報錯,我也遇到了這個坑。
configure: error: No xcodebuild tool and no system framework headers found, use --with-sysroot or --with-sdk-name to provide a path to a valid SDK
/Users/.../.../xxx.sh: line 82: 5: Bad file descriptor
configure exiting with result code 1
最終我通過官網下載https://developer.apple.com/download/more/安裝了9.4.1版本的XCode才搞定了。
下載xcode需要登錄,如果沒有賬號可以申請一個
我選擇的是手動下載xcode安裝的方式,你可以先只下載Command Line Tools (macOS 10.13) for Xcode 9.4.1 安裝看能不能解決你的問題,如果不能再下載Xcode(這個很大,大概4個多G)
編譯jdk
源碼下載好之后,我解壓放到了這個/Users/naver/jvm/jdk12-06222165c35f
目錄下,下面的命令均是在這個目錄下執行的。
bash configure --with-boot-jdk='/usr/local/jdk-11.0.2.jdk/Contents/Home' --with-debug-level=slowdebug --with-target-bits=64 --disable-warnings-as-errors --enable-dtrace --with-jvm-variants=server
--with-boot-jdk
:指定Bootstrap JDK路徑
--with-debug-level
:編譯級別,可選值為release、fastdebug、slowdebug和optimized,默認值為release,如果我們要調試的話,需要設定為fastdebug或者slowdebug,建議設置為slowdebug
--with-target-bits
:指定編譯32位還是64位的虛擬機
--disable-warnings-as-errors
:避免因為警告而導致編譯過程中斷
--enable-dtrace
:開啟一個性能工具
--with-jvm-variants
:編譯特定模式下的虛擬機,一般這里編譯server模式
--with-conf-name
:指定編譯配置的名稱,如果沒有指定,則會生成默認的配置名稱macosx-x86_64-server-slowdebug,我這里采用默認生成配置
在很多場景下編譯OpenJDK都會使用--enable-ccache
參數,來通過ccache加快編譯速度,但我沒有采用,因為目前編譯速度其實不慢,再有就是如果增加了這個參數,后續導入到CLion的時候,會出現很多紅字提示,看著好像不影響使用,但總歸看著不太舒服
生成Compilation Database
在配置CLion的時候,直接import編譯好之后的jdk源碼,你會發現頭文件都是紅色的,無法找到提示,是因為CLion生產的CMakeLists.txt有問題,如果想要解決這個問題就需要修改這個文件,很明顯我不會修。
最后通過JetBrains說的利用Compilation Database (https://blog.jetbrains.com/clion/2020/03/openjdk-with-clion/) 在CLion中構建OpenJDK解決了這個問題。
make CONF=macosx-x86_64-server-slowdebug compile-commands
執行完該命令,就會在${source_root}/build/macosx-x86_64-server-slowdebug下生成compile_commands.json文件。
編譯
在導入CLion之前,要編譯一下,因為某些模塊使用了預編譯頭,如果不編譯,CLion會在索引過程中提示找不到各種各樣的文件。
make CONF=macosx-x86_64-server-slowdebug
測試
至此,證明我們已經編譯完成了JDK12
CLion調試
導入project
在導入project之前先配置好Toolchains(Preferences進入)
配置好Toolchains后,通過File -> Open
功能,選中${source_root}/build/macosx-x86_64-server-slowdebug/compile_commands.json
,As a project
打開,這樣就導入了Compilation Database文件,接下來CLion開始進行索引。
這時候,你會發現你是看不到源碼的,所以下面需要修改項目的根目錄,通過Tools -> Compilation Database -> Change Project Root
功能,選中你的源碼目錄,也就是${source_root}
,這樣設置就可以在CLion中看到源代碼啦。
${source_root}指的是 /Users/naver/jvm/jdk12-06222165c35f
debug之前配置
需要在Preferences --> Build, Exceution, Deployment --> Custom Build Targets
配置構建目標
由于我這里已經配置好了,所以這里顯示的是編輯頁面,第一次配置要點擊+,進行新增即可。
通過這兩個配置每次構建之前都會重新編譯我們的jdk,修改jvm代碼之后可以直接進行重新調試。
debug 配置
Executable:選擇${source_root}/build/macosx-x86_64-server-slowdebug/jdk/bin/java
,或者其它你想調試的文件,比如javac;
Before luanch:這個下面新增的時候有一個bug,去掉就不會每次執行都去Build,節省時間,但其實OpenJDK增量編譯的方式,每次Build都很快,所以就看個人選擇了。
debug
在${source_root}/src/java.base/share/native/libjli/java.c
的401行打斷點,點擊Debug,然后F9放掉,不出意外你會遇到下面這個問題
由于我們使用的LLDB進行debug的,所以在進入第一個斷點的時候在LLDB下執行以下命令可以避免此類問題
pro hand -p true -s false SIGSEGV SIGBUS
最終就可以看到java -version的輸出效果如下
不過每次debug的時候都要輸入這么一句就很麻煩,所以我們可以在~/.lldbinit文件中,使用如下命令,實現每次Debug時自動打個斷點,然后輸入pro hand -p true -s false SIGSEGV SIGBUS
,最后繼續執行后續流程,文件內容如下(其中main.c文件的路徑自行替換)
breakpoint set --file /Users/naver/jvm/jdk12-06222165c35f/src/java.base/share/native/launcher/main.c --line 98 -C "pro hand -p true -s false SIGSEGV SIGBUS" --auto-continue true
與Java程序聯合debug
上面演示的實際是java -version如何debug,那么如何做到通過自己編寫的java代碼作為程序入口來調試呢?
首先java代碼如下(我用idea編寫的):
CLion中配置如下
運行結果如下:
參考文檔
<<深入理解Java虛擬機:JVM高級特性與最佳實踐>>
mac下編譯openjdk1.9及集成clion動態調試
在MacOS系統上使用CLion編譯并調試OpenJDK
關注我不迷路
你的關注是對我最大的鼓勵,是兄弟就關注我(狗頭保命)