本地构建Scala编译器出现java.lang.NoSuchMethodError异常求助
解决Java 8环境下Scala编译器报
NoSuchMethodError: StringBuilder.isEmpty()的问题 [Thu Aug 25 11:24:22 EDT 2022, Utils] SEVERE: Problem java.lang.NoSuchMethodError: 'boolean java.lang.StringBuilder.isEmpty()' at scala.tools.nsc.ast.parser.Scanners$Scanner.checkNoTrailingSeparator(Scanners.scala:1264) at scala.tools.nsc.ast.parser.Scanners$Scanner.getNumber(Scanners.scala:1302) at scala.tools.nsc.ast.parser.Scanners$Scanner.fetchToken(Scanners.scala:632) at scala.tools.nsc.ast.parser.Scanners$Scanner.nextToken(Scanners.scala:422) ... at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.compile(IMain.scala:744)
核心原因
StringBuilder.isEmpty()是Java 11新增的方法,Java 8标准库中不存在该方法。你遇到的问题是因为本地构建Scala 2.13.6编译器时,使用了Java 11或更高版本的JDK编译,导致生成的字节码直接调用了这个Java 11特有方法,在Java 8运行环境下触发NoSuchMethodError。
解决步骤
切换到Java 8环境重新构建编译器
- 必须使用Java 8的JDK完成Scala编译器的构建,高版本JDK即使指定目标版本,仍可能将Scala代码中的空判断编译为
isEmpty()调用,而非Java 8兼容的length() == 0写法。 - 操作流程:
- 将环境变量
JAVA_HOME指向Java 8安装路径 - 清理构建缓存:执行
sbt clean(基于sbt构建时) - 重新执行构建命令,确保全程使用Java 8环境
- 将环境变量
- 必须使用Java 8的JDK完成Scala编译器的构建,高版本JDK即使指定目标版本,仍可能将Scala代码中的空判断编译为
强制指定JVM目标版本为1.8
- 在构建脚本中明确声明编译目标,避免编译器自动使用高版本特性:
- 若用sbt,在
build.sbt中添加:scalacOptions ++= Seq("-target:jvm-1.8") javacOptions ++= Seq("-source", "1.8", "-target", "1.8") - 若用maven,在pom.xml中配置编译插件参数,确保目标JDK版本为1.8
- 若用sbt,在
- 在构建脚本中明确声明编译目标,避免编译器自动使用高版本特性:
验证构建产物兼容性
- 使用
javap工具检查编译后的类文件,确认未调用Java 11 API:javap -c scala.tools.nsc.ast.parser.Scanners$Scanner | grep -A2 -B2 isEmpty- 若输出出现
invokevirtual #xxx // Method java/lang/StringBuilder.isEmpty:()Z,说明构建仍不兼容;若显示调用length()并执行空判断,则说明符合Java 8要求
- 若输出出现
- 使用
调试思路
- 检查应用类路径:确保目标应用的类路径中没有混入高版本Scala jar包或非Java 8类库,避免类加载冲突
- 启用类加载日志:启动应用时添加
-verbose:class参数,查看StringBuilder类的加载来源,确认是Java 8标准库 - 替换jar包后测试:将重新构建的compiler/reflect/library三个jar包替换到目标应用中,重新运行验证异常是否消失
内容的提问来源于stack exchange,提问作者Ben Bulent Basaran
相关产品推荐
相关产品推荐

