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


我正在尝试运行一个打包为JAR(包括依赖项)的Scala应用程序,但是这个失败直到使用 -Xbootclasspath/p 选项。

调用失败:

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

在应用程序执行了一些预期输出后,控制台显示:

线程“main”中的异常   scala.reflect.internal.MissingRequirementError:object 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)           at scala.reflect.internal.Definitions $ DefinitionsClass.RuntimePackage $ lzycompute(Definitions.scala:181)           在scala.reflect.internal.Definitions $ DefinitionsClass.RuntimePackage(Definitions.scala:181)           at scala.reflect.internal.Definitions $ DefinitionsClass.RuntimePackageClass $ lzycompute(Definitions.scala:182)           在scala.reflect.internal.Definitions $ DefinitionsClass.RuntimePackageClass(Definitions.scala:182)           at scala.reflect.internal.Definitions $ DefinitionsClass.AnnotationDefaultAttr $ lzycompute(Definitions.scala:1015)           at scala.reflect.internal.Definitions $ DefinitionsClass.AnnotationDefaultAttr(Definitions.scala:1014)           at scala.reflect.internal.Definitions $ DefinitionsClass.syntheticCoreClasses $ lzycompute(Definitions.scala:1144)           在scala.reflect.internal.Definitions $ DefinitionsClass.syntheticCoreClasses(Definitions.scala:1143)           at scala.reflect.internal.Definitions $ DefinitionsClass.symbolsNotPresentInBytecode $ lzycompute(Definitions.scala:1187)           at 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-compiler 和 scala-reflect 被定义为依赖关系 build.sbt

对于古玩/背景信息

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

问题

  • 鉴于Scala库包含在JAR文件中,为什么需要使用JAR调用JAR -Xbootclasspath/p:scala-library.jar
  • 为什么应用程序的其他部分运行得很好 scala.runtime 据报道以后失踪?

11173
2017-08-09 16:00


起源

这可能是因为您没有给该编译器运行使用任何类路径。代替 Global(new Settings()),尝试给它一个与程序具有相同类路径的设置: settings.classpath.value = System.getProperty("java.class.path")。 - gourlaysama
或者可能 settings.usejavacp.value = true或类似的东西...... - gourlaysama
非常感谢您的评论。我似乎错误地认为编译器设置默认为调用程序的设置。添加其中一个 settings.usejavacp.value = true 要么 settings processArgumentString "-usejavacp" 将导致正确配置的编译器,从而产生一个工作程序。 - Augustus Kling


答案:


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

  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

奖金信息,我碰巧碰到了 启用提交消息

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

** 公共服务声明 **

如果您的代码停止使用此提交(大多数情况下)   很可能,错误就像是“找不到对象标量”,你可以   让它再次使用以下任何一个:

在命令行上传递-usejavacp

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

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


9
2017-08-09 17:21



对于在Intellij IDEA中配置Scala时出现类似错误的任何人,将其添加到“项目结构 - >构面 - > Scala - >编译器选项”中的“其他编译器选项”:“ - usejavacp”我成功地使用它来解决致命错误:对象未找到编译器镜像中的scala.beans.BeanInfo。 - Malcolm