13

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

调用失败:

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

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

线程“主”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。在 scala.reflect.internal.Mirrors$RootsBase.getRequiredPackage(Mirrors.scala:175) 在 scala.reflect.internal.Definitions$DefinitionsClass 的 Mirrors$RootsBase.getPackage(Mirrors.scala:172)。

工作调用:

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.sbtassembly调用了目标。一个大约 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,以便在其中找到方法调用。

问题

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

1 回答 1

10

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

  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 的电子邮件中的描述实现类路径,理论上我必须知道我在做什么。

** 公共服务声明 **

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

在命令行上传递 -usejavacp

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

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

于 2013-08-09T17:21:14.380 回答