寫 Java 這麼久了,來編譯個 JDK 玩玩兒吧

你每天寫的 Java 代碼都需要 JDK 的支持,都要跑在 JVM 上,難道你就不好奇 JDK 長什麼樣子嗎。好奇,就來編譯並實現一個自己的 JDK 吧。

本次編譯環境 macOS 10.12,編譯的是 JDK 11 版本。

安裝 OpenJDK 11

編譯 OpenJDK 需要先在機器上安裝 OpenJDK 10 或者 OpenJDK 11,作為 Boot JDK。
先安裝 openJDK 11 編譯需要,可以到 adoptopenjdk 網站去下載。

pkg 格式安裝

進入頁面 https://adoptopenjdk.net/index.html?variant=openjdk11&jvmVariant=hotspot 直接下載下載,然後雙擊就可以完成安裝了。

tar.gz 格式安裝

1、進入頁面 https://adoptopenjdk.net/installation.html?variant=openjdk11&jvmVariant=hotspot#x64_mac-jdk 下載 tar.gz 包

2、解壓

<code>tar -xf OpenJDK11U-jdk_x64_mac_hotspot_11.0.5_10.tar.gz/<code>

解壓後是一個 macOS 包,可通過右鍵->顯示包內容查看裡面的文件。

3、加入環境變量 PATH 中,當然如果你使用其他版本的 JDK 作為開發使用,請忽略這一步。

<code>export PATH=$PWD/jdk-11.0.5+10/Contents/Home/bin:$PATH/<code>

4、macOS JDK 默認目錄在/Library/Java/JavaVirtualMachines,把第 2 步解壓的內容放到此目錄下,之後編譯的過程中會在這個目錄下查找 JDK 10 或 JDK 11。

下面是我本地的目錄結構,有 7 、8、11 這三個版本,開發時候還是默認使用 8 的。

寫 Java 這麼久了,來編譯個 JDK 玩玩兒吧

安裝 xcode

實際上我們需要的不是 xcode,而是 LLVM 的編譯命令 clang。當然你可以單獨安裝 LLVM,但限於此篇是寫給 Java 開發者的,安裝 xcode 是最簡單的版本。

我本地是很早之前安裝的 xcode 8.1,編譯起來是沒問題的,如果你用的是比較新的版本,應該也不會出現什麼問題,可以親自試一試。

開始編譯

1、下載 OpenJDK 11 源碼

OpenJDK 的源碼放在了網站 http://hg.openjdk.java.net/ 上,我們要下載的 JDK11 目錄在 http://hg.openjdk.java.net/jdk-updates/jdk11u/。

進入頁面後,先點擊左側的 browse,再選擇一種壓縮格式下載。

寫 Java 這麼久了,來編譯個 JDK 玩玩兒吧

當然還可以用 hg 命令 clone 到本地,使用 hg 需要安裝 mercurial,如果網速不好或者不穩定,建議不要使用這種方式。

<code>hg clone https://hg.openjdk.java.net/jdk/jdk11//<code>

2、解壓源碼包

將你剛剛下載的壓縮包解壓,請解壓到一個全英文目錄下,不要使用中文,減少編譯時帶來的麻煩。

3、configure

進入上一步解壓後的目錄,執行如下命令。

<code>sh configure --with-target-bits=64 --enable-ccache --with-jvm-variants=server  --with-boot-jdk-jvmargs="-Xlint:deprecation -Xlint:unchecked" --disable-warnings-as-errors --with-debug-level=slowdebug 2>&1 | tee configure_mac_x64.log/<code>

執行這個命令的前提是我已經將 OpenJDK 11 放到了 /Library/Java/JavaVirtualMachines目錄下。

如果不放到這個目錄下,也是可以的,需要額外指定參數

<code>--with-boot-jdk=OpenJDK 目錄/<code>

如果出現如下輸出,說明這一步就正常了。

寫 Java 這麼久了,來編譯個 JDK 玩玩兒吧

4、make

正式開始編譯了,使用 make 命令即可。

<code>make/<code>

首次編譯會比較慢,我的是 MacBook Pro i5 8G 的那款,大概編譯了 10 幾分鐘吧。當出現如下輸出的時候,說明編譯成功。

<code>Finished building target 'default (exploded-image)' in configuration 'macosx-x86_64-normal-server-slowdebug'/<code>

編譯好之後,會在當前目錄出現 build 目錄,進去之後,看到有個 macosx-x86_64-normal-server-slowdebug 就是最終的目錄。

IDEA 中配置使用編譯好的 JDK

1、打開 IDEA ,找到 File->Project Structure。

寫 Java 這麼久了,來編譯個 JDK 玩玩兒吧

2、添加一個 JDK

寫 Java 這麼久了,來編譯個 JDK 玩玩兒吧

3、選擇上面源碼編譯好的 jdk

寫 Java 這麼久了,來編譯個 JDK 玩玩兒吧

4、最後啟動項目的時候指定這個 JDK 就可以了。

用 CLion 調試

1、打開 CLion ,導入項目,選擇下載的源碼所在位置的 src 目錄。

寫 Java 這麼久了,來編譯個 JDK 玩玩兒吧

2、配置 Debug Configurations,選擇 Executable 為編譯好的 java 可執行程序,在 bin 目錄下,並且移除 Build 設置。

Program arguments 設置為 -version,也可以設置其他的。設置為 -version 的意思是 java -version。

寫 Java 這麼久了,來編譯個 JDK 玩玩兒吧

3、最後在源碼中打個斷點,比如 jni.cpp 或 thread.cpp 中,然後點擊 debug ,就可以調試啦。

打造自己的 JDK

標題說的有點兒懸,打造自己的 JDK 哪兒有那麼容易,況且還確實沒那個實力。這裡就是介紹一種思路,比如有些時候,我們調試 Java 代碼最後發現走到了 JVM 層,這種情況下,我們就跟不進去了。執行到 JVM 層之後,裡面的各種變量是怎麼變換的我們就不知道了。這時候,我們找到 JVM 對應的代碼稍微改一下,比如加個 printf 輸出一下參數值就可以清晰的看出來了。

修改 JDK 代碼

我在打開的 CLion 中找到了 java.c 文件的 JavaMain(void * _args) 方法,在裡面加了一行打印代碼,就勉強算實現了自己的 JDK 吧(微笑臉)。

萬里長征第一步嘛,別的不重要,留下腳印兒才是關鍵。

<code>printf("古時的風箏 JDK \\n");/<code>
寫 Java 這麼久了,來編譯個 JDK 玩玩兒吧

重新編譯修改後的源碼

修改之後,在終端中進入到源碼目錄的根目錄,然後執行 make 命令。

因為之前已經編譯過了,所以再次執行 make 是進行的增量編譯,所以速度很快。

好了,見證奇蹟的時刻到了

我們之前已經在 IDEA 中添加了編譯好的 JDK,並且指定給了一個項目。僅為測試,代碼如下。

<code>public static void main(String[] args){
System.out.println("hello jvm");
}/<code>

當我們運行這個項目的時候,如果是平常的 JDK,會在控制檯輸出 hello jvm ,對不對。

可是,現在指定的不是平常的 JDK ,是被我加持過的 JDK 。

開始運行,輸出的結果如下,看到沒,剛剛加上的那行代碼起作用了。

寫 Java 這麼久了,來編譯個 JDK 玩玩兒吧

風箏說

真正能做到 JDK 定製開發的人並不多,我也完全沒這個實力。但是每個 Java 開發者都編譯一下 JDK 源碼,翻一翻代碼還是很有必要的。畢竟,我們每天寫的代碼都需要 JDK 的支持,都要跑在 JVM 上,我們就不好奇它們長成什麼模樣嗎。

另外,這也可能為我們日常解決問題提供一種思路。有人說,最好的老師就是搜索引擎,大多數情況下是沒錯,但有的時候最好的方式往往就是看一眼源碼。

為什麼有的人解決問題的速度快,有些看似不能解決的問題放到大牛手裡就能很快解決。有時候就是解決問題的維度不一樣,人家是在三維的世界裡,你卻一直在二維的平面裡轉圈圈,比方說遇到程序問題,只能分析 Java 層面的問題這就是二維,進到 JDK、JVM 源碼那就是進到的三維。維度高了,角度變了,解決問題的可能性和方式也就多了。這就好比三體裡高等文明利用二向箔進行打擊,完全不在一個體量下。

趕緊行動吧,編譯一個你自己的 JDK。

來源:https://www.cnblogs.com/fengzheng/p/12168903.html


分享到:


相關文章: