SpringBoot Jar包无法通过java -cp手动运行主类问题咨询
哈哈,这个问题我当初刚用Spring Boot的时候也卡了好久!核心原因是Spring Boot打包出来的可执行Jar结构和普通Jar完全不一样,直接用java -cp指定主类根本找不到对应的class文件。
java -cp找不到Spring Boot Jar里的主类? Spring Boot的可执行Jar采用了嵌套Jar结构,和传统Jar的布局差异很大:
- 普通Jar的类文件直接放在根目录下,classpath能直接扫描到;
- 而Spring Boot Jar里,你的业务类都被打包到
BOOT-INF/classes/目录下,第三方依赖则在BOOT-INF/lib/里,根目录下只有Spring Boot自己的启动加载类(比如org.springframework.boot.loader.JarLauncher)。
当你用java -jar运行时,Jar的MANIFEST.MF文件里已经指定了Main-Class为org.springframework.boot.loader.JarLauncher,这个类会帮你处理嵌套结构,加载BOOT-INF下的类和依赖,再启动你真正的主类(通过Start-Class属性指定,也就是你的@SpringBootApplication类)。
但java -cp只会扫描Jar根目录下的类,不会自动识别BOOT-INF/classes,所以直接指定com.test.MyScript或者com.test.MyApplication自然会提示找不到主类。
java -cp手动运行主类? 有几种可行的方法:
方法1:借助Spring Boot的MainMethodRunner类
Spring Boot提供了专门的类来帮你加载嵌套结构里的主类,命令格式如下:
# 运行你的自定义脚本类 java -cp my-project.jar org.springframework.boot.loader.MainMethodRunner com.test.MyScript # 运行Spring Boot应用主类 java -cp my-project.jar org.springframework.boot.loader.MainMethodRunner com.test.MyApplication
这个MainMethodRunner会负责解析BOOT-INF下的类路径,找到你指定的主类并执行。
方法2:解压Jar后手动指定完整classpath
把Spring Boot Jar解压到某个目录,然后把BOOT-INF/classes和BOOT-INF/lib下的所有依赖Jar都加入classpath:
# Linux/macOS java -cp "BOOT-INF/classes:BOOT-INF/lib/*" com.test.MyScript # Windows java -cp "BOOT-INF/classes;BOOT-INF/lib/*" com.test.MyScript
这种方法比较繁琐,适合临时调试用。
方法3:打包时单独配置(推荐)
如果你的MyScript是独立的脚本类,建议在构建工具(Maven/Gradle)里配置Spring Boot插件,单独为它生成一个可执行Jar,或者直接用exec插件在打包前运行:
- Maven可以用
exec:java插件直接运行com.test.MyScript,不用打包; - 也可以在Spring Boot插件里配置多个启动类,打包时指定不同的主类。
可以先执行jar tf my-project.jar查看Jar的结构,确认com/test/MyScript.class确实在BOOT-INF/classes/目录下,避免是打包时漏了类的问题。
内容的提问来源于stack exchange,提问作者xuanzhui

