1. 程式人生 > 其它 >編譯jdk和使用clion除錯jdk

編譯jdk和使用clion除錯jdk

前言

我們都知道java程式是執行在jvm虛擬機器上的,jdk裡面很多native方法的實現都是在jvm原始碼裡面的。那麼jvm是如何載入類,如何建立物件,執行緒同步的本質是什麼?那些看不見的native方法到底幹了什麼?這些疑問使用baidu或許能瞭解個大概。但通過百度獲取的知識,如果自己沒有消化,只是臨時解決某個問題,或者面試的時候背誦一下。我想這是無意義的。因為過了一段時間後,你會忘了它。甚至一點印象都沒有了。那麼怎麼把這些知識深深的刻在腦海裡呢。其實我覺得沒必要。為什麼要記住這些死板的知識點呢。舉個例子,面試的時候面試官可能會問你java nio底層依賴的epoll機制一共有涉及幾個系統呼叫。答案是epoll_create

epoll_ctlepoll_wait這三個。但真的有必要記住他們嗎。我想也就大概面試的時候會用到吧。而且還是面試一般開發崗位的時候會問到。其實找下jdk原始碼不就知道了,沒必要刻意記住這些東西。接下來我會使用幾篇文章講解如何搭建本地jvm的除錯環境,如何除錯native方法。如何除錯jvm啟動過程。當然這些只是開啟jvm大門的鑰匙。要想深入理解還需要一點一滴的積累。

環境準備

我的作業系統:mac os Big Sur 版本11.4

  1. 下載clion,我的版本是2019.3.6
  2. git clone openjdk12
  3. 安裝jdk11,編譯jdk12需要使用引導的jdk,否則會提示Your Boot JDK version must be one of 11,12

編譯jdk

進入openjdk的根目錄執行

bash configure --disable-warnings-as-errors --with-debug-level=slowdebug --with-jvm-variants=server
make images
# disable-warnings-as-errors選項是禁止把warning 當成error
# --with-debug-level=slowdebug。用來設定編譯的級別,可選值為release、fastdebug、slowde-bug,越往後進行的優化措施就越少,帶的除錯資訊就越多。預設值為release。slowdebug 含有最豐富的除錯資訊,沒有這些資訊,很多執行可能被優化掉,我們單步執行時,可能看不到一些變數的值。所以最好指定slowdebug 為編譯級別。
# with-jvm-variants 編譯特定模式的HotSpot虛擬機器,可選值:server、client、minimal、core、zero、custom

configure 命令承擔了依賴項檢查引數配置構建輸出目錄結構等多項職責,如果編譯過程中需要的工具鏈或者依賴項有缺失,命令執行後會得到明確的提示,並給出該依賴的安裝命令。

漫長的等待之後,一個自己的jdk誕生了。它的目錄結構是這個樣子的

使用clion除錯hotspot虛擬機器

下面的操作主要參考這篇部落格https://blog.jetbrains.com/clion/2020/03/openjdk-with-clion/

compilation database 這個功能大概的意思就是clion預設是用cmake,但是編譯openjdk是用make,可以通過下面這個辦法解決

If you are working with a project which is not based on CMake, Gradle, or Makefiles, you can still benefit from the advanced IDE features that CLion provides. One way is to import a non-CMake project and let CLion convert it into a simple CMake structure. Another option is to open a project by loading its compilation database

生成compile_commands.json檔案

make compile-commands

使用CLion File=> Open => 選擇檔案

/jdk12/build/macosx-x86_64-server-slowdebug/compile_commands.json

選擇open as Project

這時候,你會發現你是看不到原始碼的,所以下面需要修改專案的根目錄,通過Tools -> Compilation Database -> Change Project Root功能,選中你的原始碼目錄,也就是jdk12

Custom Build Targets
Run/Debug configurations

設定斷點,進行debug

此處只是簡單地演示了java -version如何debug。那如果是一個普通的java程式如何debug呢。

寫一個測試程式如下:

public class Demo {
    public static void main(String[] args) throws Exception {
        LockSupport.park();
    }
}

檢視原始碼發現park方法實際呼叫的是Unsafe類的park方法。而這個native方法的原始碼位於/jdk12/src/hotspot/share/runtime/park.hpp下,它的實現類是/jdk12/src/hotspot/os/posix/os_posix.cpp。配置除錯程式的引數。

os_posix.cpp中設定斷點。

可以看出最終呼叫pthread_cond_wait這個系統呼叫,執行緒等待在那裡。

這只是一個簡單的例子演示瞭如何使用Clion除錯java程式。按照這個方法就可以對任何native方法進行單步除錯。

IDEA配合Clion遠端除錯

上面我們實現了除錯hotspot虛擬機器。如果我想java程式和hotspot虛擬機器一起除錯,該如何實現呢?這就需要使用到jvm的遠端debug功能了。

比如新建一個簡單的spring boot專案,使用maven生成可執行的jar包。

clion配置如下:

idea配置如下:

這樣不論是在clion下設定斷點還是在idea下設定斷點,都可以進行單步除錯啦。

總結

這篇文章簡單介紹了下除錯openjdk的環境和工具的使用。後面會出幾期針對特點知識點的深入hotspot原始碼的解析教程。敬請期待。