開篇
學習源碼第一步就是搭建調試環境,但是看了網上大部分Elasticsearch調試方式都是配置各種環境變量然後直接啓動Main方法,而且還各種報錯。今天提供新的方式--remote debug來避免這些麻煩。
步驟
環境
首先要安裝jdk8,gradle和Intellij IDEA
源碼下載
拉取代碼,checkout到想要調試的版本(這裏切到v6.1.0,需要注意的是不同ES分支對gradle版本要求不一樣,可以到README文件中查看對應到gradle版本要求)
git clone [email protected]/elastic/elasticsearch
cd elasticsearch
git checkout v6.1.0
導入到IDEA
執行gradle idea,成功後會提示BUILD SUCCESSFUL,然後導入到IDEA
:test:fixtures:hdfs-fixture:idea
:test:fixtures:krb5kdc-fixture:ideaModule
:test:fixtures:krb5kdc-fixture:idea
:test:fixtures:old-elasticsearch:ideaModule
:test:fixtures:old-elasticsearch:idea
BUILD SUCCESSFUL
Total time: 2 mins 2.159 secs
使用gradle啓動Elasticsearch
gradle run --debug-jvm
執行成功後是這樣的,其中8000就是遠程debug端口
配置remote debug
點擊IDEA的Edit Configurations,再點擊➕
填寫主機和端口,Name是配置名稱,可以自定義(我這裏就填es),點OK保存配置
搜一下源碼裏面Elasticsearch類,,看到Main方法,先打個斷點等會看效果
最後再點下綠色小蟲子啓動debug
是不是在斷點停下來了
跳過斷點再看下控制檯,是不是啓動日誌都出來了
再驗證下是否啓動成功
原理
一切源於被稱作 Agent 的東西。JVM有一種特性,可以允許外部的庫(Java或C++寫的libraries)在運行時注入到 JVM 中。這些外部的庫就稱作 Agents, 他們有能力修改運行中 .class 文件的內容。
這些 Agents 擁有的這些 JVM 的功能權限, 是在 JVM 內運行的 Java Code 所無法獲取的, 他們能用來做一些有趣的事情,比如修改運行中的源碼, 性能分析等。 像 JRebel 工具就是用了這些功能達到魔術般的效果。
傳遞一個 Agent Lib 給 JVM, 通過添加 agentlib:libname[=options] 格式的啓動參數即可辦到。像上面的遠程調試我們用的就是 -agentlib:jdwp=... 來引入 jdwp 這個 Agent 的。
jdwp 是一個 JVM 特定的 JDWP(Java Debug Wire Protocol) 可選實現,用來定義調試者與運行JVM之間的通訊,它的是通過 JVM 本地庫的 jdwp.so 或者 jdwp.dll 支持實現的。簡單來說, jdwp agent 會建立運行應用的 JVM 和調試者(本地或者遠程)之間的橋樑。既然他是一個Agent Library, 它就有能力攔截運行的代碼。
在 JVM 架構裏, debugging 功能在 JVM 本身的內部是找不到的,它是一種抽象到外部工具的方式(也稱作調試者 debugger)。這些調試工具或者運行在 JVM 的本地 或者在遠程。這是一種解耦,模塊化的架構。
關於Agent還有很多值得研究的細節,甚至基於JVMTI自己實現。參考https://www.ibm.com/developerworks/cn/java/j-lo-jpda2/index.html