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.Mirrors$RootsBase.getModuleOrClass(Mirrors) で scala.reflect.internal.MissingRequirementError$.signal(MissingRequirementError.scala:16) で scala.reflect.internal.MissingRequirementError$.notFound(MissingRequirementError.scala:17) で.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) at scala.reflect.internal.Mirrors$RootsBase.getRequiredPackage(Mirrors.scala:175) at scala.reflect.internal.Definitions$DefinitionsClass.

作業呼び出し:

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 ライブラリを含むすべての依存関係が含まれるようにビルドされていることです。scala.runtimeJAR ファイルを抽出すると、パッケージ内のクラス ファイルが含まれていることが確認できます。

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-compilerおよびscala-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」に設定

これらのいずれも、Java アプリケーションのクラスパスを scala でも利用するように scala に警告します。

于 2013-08-09T17:21:14.380 に答える