【曹工雜談】Maven原始碼除錯工程搭建

三國夢迴發表於2021-09-08

Maven原始碼除錯工程搭建

思路

我們前面的文章《【曹工雜談】Maven和Tomcat能有啥聯絡呢,都穿打補丁的衣服嗎》分析了Maven大體的執行階段,主要包括三個階段:

  1. 啟動類階段,負責載入框架;

  2. 框架核心(maven core)階段,主要負責根據引數中的goal,如clean,找到對應的外掛的jar包,生成外掛物件,解析引數並呼叫外掛程式碼;

  3. 外掛執行階段,執行完成後,控制權會交還給框架核心,由maven core完成善後工作。

這三個階段,分別會去不同的地方載入對應的jar包。

大概瞭解了這個流程後,我們開始思考,我們到底要除錯哪一部分的程式碼。

  • 如果我們要除錯階段一的程式碼,那麼,又分兩種情況,是否需要改動階段一的程式碼,如果需要改動,那麼,就要找到階段一的jar的原始碼,然後載入到idea中,並且,啟動除錯的時候,也需把classpath指定到我們的原始碼工程;如果不需要改動,那就可以參考:《【曹工雜談】詳解Maven外掛除錯方法》,直接把jar包引入idea的project classpath即可。
  • 如果我們需要除錯階段二的程式碼,那麼,也分兩種情況,需要改動程式碼,就去找原始碼,然後引入到idea;同時,階段一去找階段二的時候,預設還是去了%MAVEN_HOME%/lib/*.jar下邊去找,我們這時候就得糾正它的錯誤行為,讓它轉而去我們的原始碼工程下找階段二的程式碼。
  • 如果需要除錯階段三的程式碼,如果需要改動,預設也是要引入外掛的原始碼工程;但是,階段二,去找外掛程式碼的時候,要讓它去我們的原始碼工程下找程式碼是比較困難的(預設就是去本地倉庫找,要糾正這個行為,難度較大),因此,就算了。我們還是會引入外掛的原始碼,但是,每次改了外掛程式碼,手動部署到本地倉庫就行。

我們接下來,就開始實現上面的三個目標。

搭建階段三的除錯工程

大部分人可能感興趣的還是外掛程式碼,想自己搭著玩的,可以參考:《【曹工雜談】詳解Maven外掛除錯方法

但是在這裡,我還是需要基於我在gitee上新建的一個倉庫,來給大家講解。後續的原始碼分析文章(如果有的話)也會基於這個工程來講解。

程式碼在這裡:https://gitee.com/ckl111/maven-3.8.1-source-learn

下邊介紹下目錄結構:

  • test-maven-core,用來在這個module的pom上,執行mvn clean等命令
  • plugin-sources,用來存放外掛的程式碼,後續的外掛原始碼都會往這裡放
  • plexus-classworlds-source,用來存放階段一的那個啟動類的原始碼
  • 除此之外,都是maven框架本身的原始碼,這部分,統稱為maven core

下載了原始碼後,進行idea匯入,匯入時,選擇這個主目錄下的pom,這個pom,就是框架核心的pom,預設只會匯入框架核心的maven工程;我們還需要手動,把test-maven-core、plugin-sources、plexus-classworlds-source都匯入一下(對著pom右鍵,Mark As Maven Project即可)。

匯入完成後,我們預設會有4個root maven工程,其中,最上面的那個Apache Maven,就是maven核心框架。

接下來,也簡單了,如果不需要修改程式碼的話,那就可以在任意位置打斷點了。打完斷點,怎麼觸發呢, 下邊這樣就行了。

我這邊已經ok了,你呢?

如果想修改外掛程式碼,改完後,記得mvn install外掛到本地倉庫。

搭建階段二的除錯工程

如果大家只是想跟著程式碼debug,那麼,直接在maven框架對應的類上打斷點就行了,下圖就是在maven core這個module上打斷點。

如果可能自己想改改maven原始碼、輔助學習的話,我們就得動點心思。

在此之前,我們需要把整個maven框架核心,先編譯一次,因此,在G:\gitee-projects\maven-3.8.1-source-learn(只是我這邊的目錄)下,執行:

mvn -DskipTests=true install

如果大家有報錯,什麼rat相關的,可以來這裡:

把這個外掛元素(元素)刪掉。

我這邊還遇到了checkstyle報錯,同樣,也在這個pom裡,把checkstyle檢查刪掉。

最終呢,還是執行ok了。

上面這步ok後,在昨天的文章裡《【曹工雜談】Maven和Tomcat能有啥聯絡呢,都穿打補丁的衣服嗎》,我們說了,maven的啟動類,是去下邊這個地方,找maven core程式碼的:

F:\tools\apache-maven-3.8.1-bin\apache-maven-3.8.1\bin\m2.conf.

檔案內容原本是這樣的:

main is org.apache.maven.cli.MavenCli from plexus.core

set maven.conf default ${maven.home}/conf

[plexus.core]
load       ${maven.conf}/logging
optionally ${maven.home}/lib/ext/*.jar
load       ${maven.home}/lib/*.jar

其中,load ${maven.home}/lib/*.jar就載入了maven的核心框架jar。這個地方,我們得改改,讓它還得去我們idea中原始碼工程下載入class。

main is org.apache.maven.cli.MavenCli from plexus.core

set maven.conf default ${maven.home}/conf

[plexus.core]
load       ${maven.conf}/logging
optionally ${maven.home}/lib/ext/*.jar
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-artifact\target\classes
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-builder-support\target\classes
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-compat\target\classes
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-core\target\classes
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-embedder\target\classes
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-model\target\classes
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-model-builder\target\classes
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-plugin-api\target\classes
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-repository-metadata\target\classes
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-resolver-provider\target\classes
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-settings\target\classes
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-settings-builder\target\classes
load       G:\gitee-projects\maven-3.8.1-source-learn\maven-slf4j-provider\target\classes
load       ${maven.home}/lib/*.jar

也就是去我們得target下載入classes。

這樣呢,我們就可以改動我們idea裡匯入的maven 核心框架的程式碼,然後compile了,compile後,class進入到對應的target目錄下,正好就在上文的m2.conf裡的路徑中。

為了驗證是否生效,我們隨便在maven核心框架打了個斷點,看看當前類的類載入器的路徑,發現確實已經ok了。

搭建階段一的除錯工程

階段一,也就是那個啟動jar包,對應的原始碼在:

我們只需要在啟動測試工程裡,把classpath指向這裡的target目錄,而不是maven安裝目錄下的plexus-classworlds-2.6.0.jar就可以了。

我們把這段複製出來,然後把其中,指向jar包的替換掉:

-classpath "G:\gitee-projects\maven-3.8.1-source-learn\target;F:\tools\apache-maven-3.8.1-bin\apache-maven-3.8.1\boot\plexus-classworlds.license;C:\Program Files\JetBrains\IntelliJ IDEA 2021.1.1\lib\idea_rt.jar"

把這段貼到maven執行的引數中即可。

總結

彙總一下:

  1. 階段一,指定classpath來除錯我們的原始碼工程:

    -classpath "G:\gitee-projects\maven-3.8.1-source-learn\target;F:\tools\apache-maven-3.8.1-bin\apache-maven-3.8.1\boot\plexus-classworlds.license;C:\Program Files\JetBrains\IntelliJ IDEA 2021.1.1\lib\idea_rt.jar"
    
  2. 階段二,框架核心階段,通過修改maven安裝目錄下的m2.conf的內容來實現

  3. 階段三,外掛原始碼階段,修改原始碼後,通過編譯部署到本地倉庫後實現

相關文章