2013-08-09 1 views
10

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:

+0

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

+1

oder vielleicht 'settings.usejavacp.value = true', oder etwas ähnliches ... – gourlaysama

+0

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. –

Antwort

9

Die einfache Möglichkeit, die Einstellungen mit vertrauten Tastenanschläge zu konfigurieren.

Noch einfacher:

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

Bonus Info, habe ich zufällig über the enabling commit message kommen:

Went ahead and implemented classpaths as described in email to scala-internals on the theory that at this point I must know what I'm doing.

** PUBLIC SERVICE ANNOUNCEMENT **

If your code of whatever kind stopped working with this commit (most likely the error is something like "object scala not found") you can get it working again with either of:

passing -usejavacp on the command line

set system property "scala.usejavacp" to "true"

Either of these will alert scala that you want the java application classpath to be utilized by scala as well.

+9

Jedem, der bei der Konfiguration von Scala in Intellij IDEA einen ähnlichen Fehler meldet, fügen Sie diesen zu "Zusätzliche Compiler-Optionen" in Projektstruktur -> Facetten -> Scala -> Compiler-Optionen hinzu: "-usejavac" Ich habe dies erfolgreich zur Lösung eines fatalen Fehlers verwendet: Objekt scala.beans.BeanInfo im Compilerspiegel nicht gefunden. – Malcolm

Verwandte Themen