前言
我們都知道java程序是運(yùn)行在jvm虛擬機(jī)上的欺殿,jdk里面很多native方法的實(shí)現(xiàn)都是在jvm源碼里面的。那么jvm是如何加載類(lèi),如何創(chuàng)建對(duì)象卷中,線程同步的本質(zhì)是什么?那些看不見(jiàn)的native方法到底干了什么渊抽?這些疑問(wèn)使用baidu
或許能了解個(gè)大概蟆豫。但通過(guò)百度獲取的知識(shí),如果自己沒(méi)有消化懒闷,只是臨時(shí)解決某個(gè)問(wèn)題十减,或者面試的時(shí)候背誦一下。我想這是無(wú)意義的愤估。因?yàn)檫^(guò)了一段時(shí)間后帮辟,你會(huì)忘了它。甚至一點(diǎn)印象都沒(méi)有了灵疮。那么怎么把這些知識(shí)深深的刻在腦海里呢织阅。其實(shí)我覺(jué)得沒(méi)必要。為什么要記住這些死板的知識(shí)點(diǎn)呢震捣。舉個(gè)例子荔棉,面試的時(shí)候面試官可能會(huì)問(wèn)你java nio底層依賴的epoll機(jī)制一共有涉及幾個(gè)系統(tǒng)調(diào)用闹炉。答案是epoll_create
,epoll_ctl
润樱,epoll_wait
這三個(gè)渣触。但真的有必要記住他們嗎。我想也就大概面試的時(shí)候會(huì)用到吧壹若。而且還是面試一般開(kāi)發(fā)崗位的時(shí)候會(huì)問(wèn)到嗅钻。其實(shí)找下jdk源碼不就知道了,沒(méi)必要刻意記住這些東西店展。接下來(lái)我會(huì)使用幾篇文章講解如何搭建本地jvm的調(diào)試環(huán)境养篓,如何調(diào)試native
方法。如何調(diào)試jvm啟動(dòng)過(guò)程赂蕴。當(dāng)然這些只是打開(kāi)jvm大門(mén)的鑰匙柳弄。要想深入理解還需要一點(diǎn)一滴的積累。
環(huán)境準(zhǔn)備
我的操作系統(tǒng):mac os Big Sur 版本11.4
- 下載
clion
概说,我的版本是2019.3.6
git clone openjdk12
- 安裝jdk11碧注,編譯jdk12需要使用引導(dǎo)的jdk,否則會(huì)提示
Your Boot JDK version must be one of 11,12
編譯jdk
進(jìn)入openjdk的根目錄執(zhí)行
bash configure --disable-warnings-as-errors --with-debug-level=slowdebug --with-jvm-variants=server
make images
# disable-warnings-as-errors選項(xiàng)是禁止把warning 當(dāng)成error
# --with-debug-level=slowdebug糖赔。用來(lái)設(shè)置編譯的級(jí)別萍丐,可選值為release、fastdebug放典、slowde-bug逝变,越往后進(jìn)行的優(yōu)化措施就越少,帶的調(diào)試信息就越多刻撒。默認(rèn)值為release骨田。slowdebug 含有最豐富的調(diào)試信息,沒(méi)有這些信息声怔,很多執(zhí)行可能被優(yōu)化掉,我們單步執(zhí)行時(shí)舱呻,可能看不到一些變量的值醋火。所以最好指定slowdebug 為編譯級(jí)別。
# with-jvm-variants 編譯特定模式的HotSpot虛擬機(jī)箱吕,可選值:server芥驳、client、minimal茬高、core兆旬、zero、custom
configure 命令承擔(dān)了依賴項(xiàng)檢查
怎栽、參數(shù)配置
和構(gòu)建輸出目錄結(jié)構(gòu)
等多項(xiàng)職責(zé)丽猬,如果編譯過(guò)程中需要的工具鏈或者依賴項(xiàng)有缺失宿饱,命令執(zhí)行后會(huì)得到明確的提示,并給出該依賴的安裝命令脚祟。
漫長(zhǎng)的等待之后谬以,一個(gè)自己的jdk誕生了。它的目錄結(jié)構(gòu)是這個(gè)樣子的
使用clion調(diào)試hotspot虛擬機(jī)
下面的操作主要參考這篇博客https://blog.jetbrains.com/clion/2020/03/openjdk-with-clion/
compilation database 這個(gè)功能大概的意思就是clion
默認(rèn)是用cmake
由桌,但是編譯openjdk
是用make
为黎,可以通過(guò)下面這個(gè)辦法解決
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
這時(shí)候,你會(huì)發(fā)現(xiàn)你是看不到源碼的行您,所以下面需要修改項(xiàng)目的根目錄铭乾,通過(guò)Tools -> Compilation Database -> Change Project Root
功能,選中你的源碼目錄娃循,也就是jdk12
Custom Build Targets
Run/Debug configurations
設(shè)置斷點(diǎn)炕檩,進(jìn)行debug
此處只是簡(jiǎn)單地演示了java -version
如何debug。那如果是一個(gè)普通的java程序如何debug呢淮野。
寫(xiě)一個(gè)測(cè)試程序如下:
public class Demo {
public static void main(String[] args) throws Exception {
LockSupport.park();
}
}
查看源碼發(fā)現(xiàn)park方法實(shí)際調(diào)用的是Unsafe
類(lèi)的park方法捧书。而這個(gè)native
方法的源代碼位于/jdk12/src/hotspot/share/runtime/park.hpp
下,它的實(shí)現(xiàn)類(lèi)是/jdk12/src/hotspot/os/posix/os_posix.cpp
骤星。配置調(diào)試程序的參數(shù)经瓷。
在os_posix.cpp
中設(shè)置斷點(diǎn)。
可以看出最終調(diào)用pthread_cond_wait
這個(gè)系統(tǒng)調(diào)用洞难,線程等待在那里舆吮。
這只是一個(gè)簡(jiǎn)單的例子演示了如何使用Clion
調(diào)試java程序。按照這個(gè)方法就可以對(duì)任何native
方法進(jìn)行單步調(diào)試队贱。
IDEA配合Clion遠(yuǎn)程調(diào)試
上面我們實(shí)現(xiàn)了調(diào)試hotspot虛擬機(jī)色冀。如果我想java程序和hotspot虛擬機(jī)一起調(diào)試,該如何實(shí)現(xiàn)呢柱嫌?這就需要使用到j(luò)vm的遠(yuǎn)程debug功能了锋恬。
比如新建一個(gè)簡(jiǎn)單的spring boot項(xiàng)目,使用maven生成可執(zhí)行的jar包编丘。
clion配置如下:
idea配置如下:
這樣不論是在clion下設(shè)置斷點(diǎn)還是在idea下設(shè)置斷點(diǎn)与学,都可以進(jìn)行單步調(diào)試?yán)病?/p>
總結(jié)
這篇文章簡(jiǎn)單介紹了下調(diào)試openjdk的環(huán)境和工具的使用。后面會(huì)出幾期針對(duì)特點(diǎn)知識(shí)點(diǎn)的深入hotspot源碼的解析教程嘉抓。敬請(qǐng)期待索守。