Ich versuche, eine Scala-Anwendung als JAR (einschließlich Abhängigkeiten) ausgeführt, aber das scheitert bis die Scala Bibliothek wird mit der Option -Xbootclasspath/p
hinzugefügt."scala.runtime im Compiler-Spiegel nicht gefunden", aber funktioniert, wenn mit -Xbootclasspath/p gestartet: scala-library.jar
Failing Aufruf:
java -jar /path/to/target/scala-2.10/application-assembly-1.0.jar
Nachdem die Anwendung einiger seiner beabsichtigten Ausgabe hat, die Konsole zeigt:
Exception in thread "main" scala.reflect.internal.MissingRequirementError: object scala.runtime in compiler mirror not found. at scala.reflect.internal.MissingRequirementError$.signal(MissingRequirementError.scala:16) at scala.reflect.internal.MissingRequirementError$.notFound(MissingRequirementError.scala:17) at scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:48) at scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:40) at scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:61) at 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.RuntimePackage$lzycompute(Definitions.scala:181) at scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackage(Definitions.scala:181) at scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackageClass$lzycompute(Definitions.scala:182) at 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) at 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) at scala.reflect.internal.Definitions$DefinitionsClass.init(Definitions.scala:1252) at scala.tools.nsc.Global$Run.(Global.scala:1290) at extract.ScalaExtractor$Compiler$2$.(ScalaExtractor.scala:24)
Arbeitsaufruf:
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
Das Merkwürdige daran ist, dass die application-assembly-1.0.jar
wurde so gebaut, dass es alle Abhängigkeiten einschließlich enthält die Scala-Bibliothek. Wenn Sie die JAR-Datei extrahieren, können Sie überprüfen, ob die Klassendateien im Paket scala.runtime
enthalten sind.
Erstellung der JAR-Datei
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.9.1")
wurde hinzugefügt, um project/plugins.sbt
und die assembly
Ziel aufgerufen wurde. Eine JAR-Datei mit ca. 25 MB ergibt sich.
Das Erstellen der JAR mit Proguard zeigt das gleiche Laufzeitverhalten wie in der JAR-Datei der Assembly.
Anwendungscode, der die MissingRequirementError löst
Einige Anwendungscode funktioniert gut und die zuvor beschriebene Ausnahme wird, sobald die new Run
aus den folgenden Fragment ausführt ausgelöst.
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)
unter anderem scala-library
, scala-compiler
und scala-reflect
als Abhängigkeiten in build.sbt
definiert.
Für die Kuriosität/Hintergrundinformationen
Das Ziel der Anwendung ist in der Lokalisierung von Java und Scala-Programmen zu unterstützen. Die Aufgabe des obigen Codefragments besteht darin, einen AST aus einer Scala-Datei zu erhalten, um dort Methodenaufrufe zu finden.
Die Fragen
- der Scala Bibliothek Gegeben in der JAR-Datei enthalten ist, warum ist notwendig, um die JAR mit
-Xbootclasspath/p:scala-library.jar
anrufen? - Warum funktionieren andere Teile der Anwendung problemlos, obwohl
scala.runtime
später als fehlend gemeldet wird?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 }
, das funktioniert für Ihr Szenario:
könnte dies sein, weil Sie keinen Classpath zu diesem Compilerlauf zu verwenden gegeben haben. Versuchen Sie anstelle von 'Global (new Settings())', Einstellungen vorzunehmen, die denselben Klassenpfad wie Ihr Programm haben: 'settings.classpath.value = System.getProperty (" java.class.path ")'. – gourlaysama
oder vielleicht 'settings.usejavacp.value = true', oder etwas ähnliches ... – gourlaysama
Vielen Dank für Ihre Kommentare. Es scheint, ich habe fälschlicherweise angenommen, dass die Einstellungen des Compilers standardmäßig denen des aufrufenden Programms entsprechen würden. Das Hinzufügen von 'settings.usejavacp.value = true' oder' settings processArgumentString "-usejavacp" führt zu einem korrekt konfigurierten Compiler und somit zu einem funktionierenden Programm. –