SpringBoot Jar启动报object scala in compiler mirror not found异常
Scala反射初始化失败:Spring Boot Jar启动时
object scala in compiler mirror not found问题解决 问题场景
- 多模块应用:一个基于Java 11的Spring Boot HTTP模块,依赖另一个Scala模块,REST调用会触发Scala代码执行
- 用
java -jar启动打包好的Spring Boot Jar时,触发Scala编译器初始化失败,报错如下:
Caused by: scala.reflect.internal.MissingRequirementError: object scala in compiler mirror not found. at scala.reflect.internal.MissingRequirementError$.signal(MissingRequirementError.scala:24) ~[scala-reflect-2.12.16.jar!/:na] at scala.reflect.internal.MissingRequirementError$.notFound(MissingRequirementError.scala:25) ~[scala-reflect-2.12.16.jar!/:na] at scala.reflect.internal.Mirrors$RootsBase.$anonfun$getModuleOrClass$5(Mirrors.scala:61) ~[scala-reflect-2.12.16.jar!/:na] at scala.reflect.internal.Mirrors$RootsBase.getPackage(Mirrors.scala:61) ~[scala-reflect-2.12.16.jar!/:na]
- 显式用
-cp指定scala-reflect、scala-compiler、scala-library这三个Jar包,并通过Spring Boot的PropertiesLauncher启动时,反射初始化能成功,但应用其他部分会出现异常
核心原因
Spring Boot默认的JarLauncher会把所有依赖Jar打包到BOOT-INF/lib目录,用自定义的LaunchedURLClassLoader加载这些依赖。但Scala反射和编译器初始化时,需要从系统类加载器直接访问scala核心类,LaunchedURLClassLoader加载的scala Jar无法被Scala的编译器镜像识别,导致找不到scala根包。
用-cp指定Jar时,这些包被系统类加载器加载,Scala编译器能正常工作,但这种方式打破了Spring Boot的类加载隔离机制,引发其他依赖的类加载冲突或异常。
解决方案
方案1:标记Scala核心依赖为provided,用loader.path指定外部依赖
- 在Spring Boot模块的pom.xml中,修改三个Scala依赖的scope为
provided:
<dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-library</artifactId> <version>2.12.16</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-reflect</artifactId> <version>2.12.16</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-compiler</artifactId> <version>2.12.16</version> <scope>provided</scope> </dependency>
- 打包后,把这三个Scala Jar放在单独的目录(比如
./scala-libs),然后用以下命令启动:
java -Dloader.path=./scala-libs -jar scala-compiler-issue-service-1.0-SNAPSHOT.jar
这种方式既让Scala核心类被系统类加载器加载,又保留了Spring Boot的类加载隔离,避免其他模块出现异常。
方案2:排除Scala依赖在Spring Boot自定义类加载器之外(Spring Boot 2.3+)
在启动命令中添加参数,让Scala核心Jar不被Spring Boot的自定义类加载器加载,转而由系统类加载器处理:
java -jar scala-compiler-issue-service-1.0-SNAPSHOT.jar --spring.boot.classloader.exclusions=org.scala-lang:scala-library,org.scala-lang:scala-reflect,org.scala-lang:scala-compiler
也可以把配置写在application.properties里:
spring.boot.classloader.exclusions=org.scala-lang:scala-library,org.scala-lang:scala-reflect,org.scala-lang:scala-compiler
方案3:打包为War包部署
如果是Web应用,将项目打包成War包,部署到Tomcat等Servlet容器中。容器的类加载机制会让Scala核心类被系统类加载器加载,自然解决反射初始化问题。
验证方法
- 执行
mvn clean package重新打包应用 - 用上述任意一种方案启动应用
- 触发REST接口调用,确认Scala代码正常执行,且应用无其他异常
内容的提问来源于stack exchange,提问作者Alokh P
相关产品推荐
相关产品推荐

