文章前半部分是分析過程,不想看的直接拉到"重點部分"
在學習SpringBoot的時候了解到,spring-boot-maven-plugin打包生成的jar包中包含了工程需要的依賴,所以這樣的jar包可以直接運行。但是工程自身是不依賴spring-boot-loader等啟動類的(實際上spring-boot-maven-plugin插件依賴了這些啟動類的jar包,所以打包的時候可以將這些jar從遠程倉庫下載并進行repackage)。
SpringBoot插件打包生成的這種fat jar可以直接運行,最重要的一點是它實現了jar in jar的加載方式,這種fat jar的啟動類是org.springframework.boot.loader.JarLauncher,我一開始想試著在IDEA中debug JarLauncher這個啟動類來學習下加載原理,但是當我以Application形式來啟動的時候(此時我已經在dependency中依賴了spring-boot-loader),即使選了Main class,也會提示出錯。
會提示找不到Start-Class,因為沒有manifest文件。
后來我找到兩種方法,均是用jdb命令在命令行進行debug
- 解壓fat jar,直接運行
jdb org.springframework.boot.loader.JarLauncher
,然后設置斷點,敲命令debug - 參考這篇文章jdb調試運行本地jar包,通過
jdb -attach
的命令來遠程控制jar的啟動,然后仍舊敲命令debug
但是由于沒有IDE的可視化環境,用以上兩種方法debug的效率非常低下,然后我就想,IDEA既然有遠程debug的功能,估計底層也是用jdb命令來實現的,所以我就想參考第二種方法,先啟動jar,然后通過IDEA的remote方式來debug,沒想到無意中發現IDEA竟然還支持JAR Application的形式進行debug,這樣就簡單多了。
重點部分
配置好Jar Application需要的一些參數,jar包的路徑,搜索類文件的路徑即工程路徑(見下圖);
然后再在工程的pom文件中引入spring-boot-loader的依賴(因為IDEA會在工程里查找源文件,所以必須主動引入才行),在JarLauncher類上打上斷點,就可以愉快地進行debug了。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader</artifactId>
</dependency>
補上用remote的方式debug spring-boot-loader的啟動源碼
解壓打包好的jar包,進入加壓后的目錄,以如下命令直接運行org.springframework.boot.loader.JarLauncher啟動類java -agentlib:jdwp=transport=dt_socket,server=y,address=8000 org.springframework.boot.loader.JarLauncher
,(每個參數的含義可以通過java -agentlib:jdwp=help
命令查看),然后在idea中配置remote運行模式即可,Host為127.0.0.1,Port為8000即可,見下圖: