You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

运行Spring Boot可执行JAR时模块子目录缺失META-INF文件夹问题及跨环境部署疑问

问题分析与解决方案

首先,我们来拆解你遇到的问题和疑问:

关于错误中提到的JDK模块目录下的META-INF文件夹

1. 它是什么?

modules/java.rmi/META-INF/services/ 是Java模块系统(JPMS)中用于存放服务提供者接口(SPI)配置的目录。SPI是Java实现插件式扩展的机制,目录下的文件会声明某个接口的具体实现类,Java的ServiceLoader会扫描这些文件来动态加载对应实现。

但这里有个关键矛盾:ch.qos.logback.classic.spi.Configurator是logback日志框架的接口,它的配置本应该存在于logback自身JAR包的META-INF/services目录中,而不是JDK的java.rmi模块下。错误中出现这个不存在的路径,说明Spring Boot启动时的类路径扫描逻辑在你的自定义内核环境中出现了异常。

2. 它何时/如何创建?

正常情况下,JDK模块的META-INF目录是JDK安装时自带的,仅包含该模块自身的元数据和SPI配置。第三方库的SPI配置会打包在各自的JAR文件中,不会出现在JDK模块目录下。你遇到的这个路径本身是不存在的,所以它不是正常创建的,而是程序启动时错误地尝试从这个路径加载资源导致的。

3. 可执行JAR是否包含所有运行内容?

Spring Boot的可执行JAR(Fat Jar)确实会打包所有依赖(包括logback),并通过自定义类加载器管理这些依赖的加载。错误中程序尝试从JDK模块路径寻找logback的配置,说明你的自定义内核环境中,类加载器的逻辑没有正确工作——可能是自定义内核对文件系统的访问有特殊限制,或者JDK的模块系统在自定义内核下存在兼容性问题。

关于在自定义内核机器上运行JAR需要复制的内容

理论上,只需要两个核心内容:

  • 你的可执行JAR文件 hello-openjdk-0.0.1-SNAPSHOT.jar
  • 与Ubuntu机器版本一致的完整OpenJDK环境

但结合你的错误,还有几个额外的排查和优化建议:

  • 分开JDK和JAR的目录:你当前把JAR放在JDK根目录下运行,这可能导致类路径扫描混淆,建议把JAR移到单独的目录(比如/opt/app/)再执行java -jar命令。
  • 检查JDK完整性:虽然你说两台机器JDK结构一致,但可以再确认自定义内核机器上的modules/java.rmi模块是否存在,以及JDK的lib目录下的文件是否完整(比如是否缺失某些核心JAR)。
  • 排查内核的文件系统限制:自定义内核可能对文件系统的某些路径有访问控制,比如是否禁止程序读取JDK模块目录外的META-INF资源?或者是否限制了Spring Boot类加载器的文件访问权限?
  • 调整Java版本兼容性:你的pom.xml中指定java.version=11,但使用的JDK是18-internal。Spring Boot 2.5.5的官方支持范围是Java 11到17,Java 18不在支持列表中。虽然Ubuntu上能运行,但自定义内核环境可能对版本差异更敏感,建议换成Java 17或11版本的JDK再尝试。
  • 启用debug日志排查:执行java -jar hello-openjdk-0.0.1-SNAPSHOT.jar --debug启动,查看详细的类路径扫描日志,定位为什么程序会错误地去java.rmi模块下寻找logback的配置。

内容的提问来源于stack exchange,提问作者danield

火山引擎 最新活动