“未找到编译器镜像中的 scala.runtime”,但在使用 -Xbootclasspath/p:scala-library.jar 启动时工作

Posted

技术标签:

【中文标题】“未找到编译器镜像中的 scala.runtime”,但在使用 -Xbootclasspath/p:scala-library.jar 启动时工作【英文标题】:"scala.runtime in compiler mirror not found" but working when started with -Xbootclasspath/p:scala-library.jar 【发布时间】:2013-08-09 16:00:32 【问题描述】:

我正在尝试运行打包为 JAR(包括依赖项)的 Scala 应用程序,但在使用 -Xbootclasspath/p 选项添加 Scala 库之前失败。

调用失败:

java -jar /path/to/target/scala-2.10/application-assembly-1.0.jar

应用程序完成一些预期输出后,控制台显示:

线程“main”中的异常 scala.reflect.internal.MissingRequirementError:对象scala.runtime 在编译器镜像中找不到。 在 scala.reflect.internal.MissingRequirementError$.signal(MissingRequirementError.scala:16) 在 scala.reflect.internal.MissingRequirementError$.notFound(MissingRequirementError.scala:17) 在 scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:48) 在 scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:40) 在 scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:61) 在 scala.reflect.internal.Mirrors$RootsBase.getPackage(Mirrors.scala:172) 在 scala.reflect.internal.Mirrors$RootsBase.getRequiredPackage(Mirrors.scala:175) 在 scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackage$lzycompute(Definitions.scala:181) 在 scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackage(Definitions.scala:181) 在 scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackageClass$lzycompute(Definitions.scala:182) 在 scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackageClass(Definitions.scala:182) 在 scala.reflect.internal.Definitions$DefinitionsClass.AnnotationDefaultAttr$lzycompute(Definitions.scala:1015) 在 scala.reflect.internal.Definitions$DefinitionsClass.AnnotationDefaultAttr(Definitions.scala:1014) 在 scala.reflect.internal.Definitions$DefinitionsClass.syntheticCoreClasses$lzycompute(Definitions.scala:1144) 在 scala.reflect.internal.Definitions$DefinitionsClass.syntheticCoreClasses(Definitions.scala:1143) 在 scala.reflect.internal.Definitions$DefinitionsClass.symbolsNotPresentInBytecode$lzycompute(Definitions.scala:1187) 在 scala.reflect.internal.Definitions$DefinitionsClass.symbolsNotPresentInBytecode(Definitions.scala:1187) 在 scala.reflect.internal.Definitions$DefinitionsClass.init(Definitions.scala:1252) 在 scala.tools.nsc.Global$Run.(Global.scala:1290) 在 extract.ScalaExtractor$Compiler$2$.(ScalaExtractor.scala:24)

工作调用:

java -Xbootclasspath/p:/path/to/home/.sbt/boot/scala-2.10.2/lib/scala-library.jar -jar /path/to/target/scala-2.10/application-assembly-1.0.jar

关于它的奇怪之处在于 application-assembly-1.0.jar 被构建为包含所有依赖项,包括 Scala 库。当提取 JAR 文件时,可以验证 scala.runtime 包中的类文件已包含在内。

JAR 文件的创建

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.9.1") 已添加到 project/plugins.sbt 并调用了 assembly 目标。一个大约 25MB 的 JAR 文件。

使用 proguard 构建 JAR 会显示与使用程序集的 JAR 文件相同的运行时行为。

触发 MissingRequirementError 的应用程序代码

一些应用程序代码可以正常工作,只要执行以下片段中的new Run,就会触发前面描述的异常。

import scala.reflect.internal.util.BatchSourceFile
import scala.reflect.io.AbstractFile
import scala.reflect.io.Path.jfile2path
import scala.tools.nsc.Global
import scala.tools.nsc.Settings
…
import scala.tools.nsc._
object Compiler extends Global(new Settings()) 
  new Run // This is line 24 from the stack trace!

  def parse(path: File) = 
    val code = AbstractFile.getFile(path)
    val bfs = new BatchSourceFile(code, code.toCharArray)
    val parser = new syntaxAnalyzer.UnitParser(new CompilationUnit(bfs))
    parser.smartParse()
  

val ast = Compiler.parse(file)

其中,scala-libraryscala-compilerscala-reflect 被定义为 build.sbt 中的依赖项。

有关古玩/背景信息

该应用程序的目的是帮助 Java 和 Scala 程序的本地化。上面代码片段的任务是从 Scala 文件中获取 AST,以便在其中找到方法调用。

问题

鉴于 JAR 文件中包含 Scala 库,为什么需要使用 -Xbootclasspath/p:scala-library.jar 调用 JAR? 为什么即使scala.runtime 稍后被报告为丢失,应用程序的其他部分也能正常运行?

【问题讨论】:

这可能是因为您没有为该编译器运行提供任何类路径以供使用。而不是Global(new Settings()),尝试给它一个与你的程序具有相同类路径的设置:settings.classpath.value = System.getProperty("java.class.path") 或者settings.usejavacp.value = true,或者类似的东西...... 非常感谢您的 cmets。似乎我错误地假设编译器设置将默认为调用程序的设置。添加settings.usejavacp.value = truesettings processArgumentString "-usejavacp" 将生成正确配置的编译器,从而生成一个工作程序。 【参考方案1】:

使用熟悉的按键配置设置的简单方法:

  import scala.tools.nsc.Global
  import scala.tools.nsc.Settings
  def main(args: Array[String]) 
    val s = new Settings
    s processArgumentString "-usejavacp"
    val g = new Global(s)
    val r = new g.Run
  

这适用于您的场景。

更简单:

java -Dscala.usejavacp=true -jar ./scall.jar

奖金信息,我碰巧遇到了the enabling commit message:

如电子邮件中所述,继续实施类路径 scala-internals 关于在这一点上我必须知道我是什么的理论 正在做。

** 公共服务公告 **

如果您的任何类型的代码停止使用此提交(大多数 可能错误类似于“找不到对象scala”)您可以 使用以下任一方法使其再次工作:

在命令行中传递 -usejavacp

将系统属性“scala.usejavacp”设置为“true”

其中任何一个都会提醒 scala 你想要 java 应用程序 scala 也可以使用类路径。

【讨论】:

对于在 Intellij IDEA 中配置 Scala 时遇到类似错误的任何人,请将其添加到 Project Structure -> Facets -> Scala -> Compiler Options 中的“Additional compiler options”中:“-usejavacp”我成功了使用它来解决致命错误:找不到编译器镜像中的对象 scala.beans.BeanInfo。 @Malcolm,我了解了方面,但后来我找不到 Scala。我看到没有配置任何方面。按“+”添加新构面。当我单击 + 时,Scala 不是选项之一 嗯...你有 Intellij IDEA Scala 插件吗? plugins.jetbrains.com/plugin/1347-scala

以上是关于“未找到编译器镜像中的 scala.runtime”,但在使用 -Xbootclasspath/p:scala-library.jar 启动时工作的主要内容,如果未能解决你的问题,请参考以下文章