2013-08-09 24 views
10

Próbuję uruchomić aplikację Scala spakowaną jako JAR (łącznie z zależnościami), ale to się nie udaje, dopóki Scala Biblioteka jest dodawana za pomocą opcji -Xbootclasspath/p."nie znaleziono scala.runtime w lustrze kompilatora", ale działa, gdy uruchomiono z opcją -Xbootclasspath/p: scala-library.jar

Niezastosowanie inwokacja:

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

po zastosowaniu zrobił niektóre z jego przeznaczeniem wyjścia, konsola wyświetla:

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)

inwokacja robocza:

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 

Dziwną rzeczą jest to, że application-assembly-1.0.jar został zbudowany tak, że zawiera wszystkie zależności w bibliotece Scala. Po wyodrębnieniu pliku JAR można sprawdzić, czy pliki klas w pakiecie scala.runtime zostały uwzględnione.

Stworzenie JAR Plik

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.9.1") dodano project/plugins.sbt a cel assembly została wywołana. Plik JAR zawierający około 25 MB wyników.

Budowanie pliku JAR za pomocą proguard przedstawia to samo zachowanie środowiska wykonawczego, co w przypadku pliku JAR zespołu.

kod aplikacji, który wyzwala MissingRequirementError kod

niektórych zastosowaniach działa dobrze, a opisana poprzednio Wyjątkiem jest wyzwalany, gdy tylko new Run z następujących fragmentów uruchomienia.

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) 

Między innymi scala-library, scala-compiler i scala-reflect są zdefiniowane jak w zależności build.sbt.

Dla informacji osobliwości/tle

Celem aplikacji jest pomoc w lokalizacji programów Java i Scala. Zadaniem powyższego fragmentu kodu jest pobranie AST z pliku Scala w celu znalezienia tam wywołań metod.

pytania

  • Biorąc biblioteki Scala jest zawarty w pliku JAR, dlaczego jest to konieczne, aby zadzwonić do naczynia przez -Xbootclasspath/p:scala-library.jar?
  • Dlaczego inne części aplikacji działają poprawnie, mimo że zgłoszenie scala.runtime zostało zgłoszone jako brakujące później?
+0

to może być, bo nie dały żadnej ścieżki klasy do tego przebiegu kompilacji do korzystania. Zamiast "Global (new Settings())", spróbuj podać ustawienia, które mają tę samą ścieżkę klasową co twój program: 'settings.classpath.value = System.getProperty (" java.class.path ")'. – gourlaysama

+1

lub może 'settings.usejavacp.value = true' lub coś podobnego ... – gourlaysama

+0

Wielkie dzięki za komentarze. Wygląda na to, że błędnie założyłem, że ustawienia kompilatora będą domyślnymi ustawieniami programu wywołującego. Dodanie 'settings.usejavacp.value = true' lub' settings processArgumentString "-usejavacp" 'spowoduje, że poprawnie skonfigurowany kompilator, a tym samym działający program. –

Odpowiedz

9

Prosty sposób, aby skonfigurować ustawienia ze znanymi klawiszy:

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 
    } 

To działa dla scenariusza.

Jeszcze prościej

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

informacji Bonus, zdarzyło mi się natknąć the enabling commit message:

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

Dla każdego, kto dostanie podobny błąd podczas konfigurowania Scala w Intellij IDEA, dodaj to do "Dodatkowe opcje kompilatora" w Strukturze projektu -> Aspekty -> Scala -> Opcje kompilatora: "-usejavacp" Pomyślnie użyłem tego do rozwiązania błędu krytycznego: obiekt scala.beans.BeanInfo w lustrze kompilatora nie znaleziono. – Malcolm