2011-10-06 8 views
9

Proszę rozważyć następujący program testowy (używając Scala 2.9.0.1)Scala classloaders zamieszanie

object test 
{ 
    def main(args:Array[String]) = { 
    println(ClassLoader.getSystemClassLoader.getResource("toto")) 
    println(this.getClass.getClassLoader.getResource("toto")) 
    println(classOf[Object].getClassLoader) 
    } 
} 

skompilować i uruchomić go z "Cp/tmp" zawierającego plik "toto" i otrzymuję następujące wyjścia:

null 
file:/tmp/toto 
null 

=> classloader system nie zawiera ścieżkę klasy

=> klasa Obiekt ma classloader!

Czy brakuje mi czegoś lub jest to (duży) błąd w scala ?!

Dzięki, Arjun

Odpowiedz

11

Drugi zerowy jest wyjaśnione przez java.lang.Class#getClassLoader()

Zwraca ładującego klasy do klasy. Niektóre implementacje mogą używać null do reprezentowania programu ładującego klasy bootstrap. Ta metoda zwróci wartość null w takich implementacjach, jeśli ta klasa została załadowana przez moduł ładowania klasy bootstrap .

Tak, to dlaczego classOf[Object].getClassLoader zwraca NULL, to ładowany przez classloader bootstrap (jest w rt.jar, bardziej konkretnie, to w słoiku, który jest w $ JAVA_HOME/lib).

Pierwszy zerowy jest trudniejszy do wyjaśnienia. Wygląda na to, że Scala opuszcza systemowy program ładujący klasy tak, jak jest, i dodaje tylko opcje -cp do swojego programu ładującego klasy (ScalaClassLoader w scala/util/ClassLoader.scala).

stosując następujący:

object Test { 
    def main(args:Array[String]) = { 
    println(ClassLoader.getSystemClassLoader) 
    println(this.getClass.getClassLoader) 
    println(classOf[Object].getClassLoader) 
    } 
} 

i uruchomienie go z:

$ scala -cp /temp Test 

otrzymujemy następujący wynik:

[email protected] 
URLClassLoader(
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/resources.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/rt.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/jsse.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/jce.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/charsets.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/dnsns.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/localedata.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/sunjce_provider.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/sunmscapi.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/sunpkcs11.jar 
    file:/C:/DEVELO~1/scala/SCALA-~1.1/bin/../lib/jline.jar 
    file:/C:/DEVELO~1/scala/SCALA-~1.1/bin/../lib/scala-compiler.jar 
    file:/C:/DEVELO~1/scala/SCALA-~1.1/bin/../lib/scala-dbc.jar 
    file:/C:/DEVELO~1/scala/SCALA-~1.1/bin/../lib/scala-library.jar 
    file:/C:/DEVELO~1/scala/SCALA-~1.1/bin/../lib/scala-swing.jar 
    file:/C:/DEVELO~1/scala/SCALA-~1.1/bin/../lib/scalap.jar 
    file:/C:/temp/ 
) 

null 

Więc classloader systemu pozostało nietknięte, ale Scala classloader pobiera elementy z -cp dodane do niego.

Morał z opowieści: nie używaj programu ładującego klasy systemu w Scali, jeśli chcesz uzyskać dostęp do zasobów ze ścieżki klasy.

EDYCJA: Ok, zbadałem to nieco więcej i scala.bat realizuje następujące polecenie (pod czystej szyby, skrócony dla czytelności)

java.exe -Xmx256M -Xms32M -Dscala.home="xxx" -cp "libsfromscalahome" scala.tools.nsc.MainGenericRunner -cp /temp Test 

Więc opcja cp z linii poleceń jest tylko były przekazywane jako opcja do MainGenericRunner, nie Java. Sądzę, że patrząc na kod, pod unixem można określić opcję -toolcp na scala, aby uzyskać element zawarty w ścieżce klas java. Coś jak (całkowicie niesprawdzone):

$ scala -toolcp /temp Test 

Ta opcja nie jest dostępna w scala.bat. Co oznacza, że ​​jeśli pracujesz w systemie Windows, musisz dostać zasobów przy użyciu

println(this.getClass.getClassLoader.getResource("toto")) 

nie mogłem znaleźć problem w Scala Lang Issues, ale jeśli jest to dla Ciebie problem, podniesienie problemu i przedstawienia naprawa. Jestem pewien, że będą zachwyceni :-)

EDYCJA: Podniosłem to jako wydanie SI 5062 -toolcp should be available on windows, in the scala.bat, i podałem żądanie pobrania go na github.

0

Od Wikipedia's classloader article:

Klasa System ładowarka ładuje kod znajduje się na java.class.path, który mapy do zmiennej systemowej CLASSPATH.

Not sure about the second null though. Może ktoś inny może to wyjaśnić.