文章前半部分是分析过程,不想看的直接拉到"重点部分"
在学习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即可,见下图: