2011-10-06 4 views
9

Si prega di considerare il seguente programma di test (con scala 2.9.0.1)classloader Scala confusione

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

compilo ed eseguirlo con "cp/tmp" contenente un file "toto", e ho la output seguente:

null 
file:/tmp/toto 
null 

=> il classloader sistema non contiene il percorso di classe

=> della classe Object non ha classloader!

Mi manca qualcosa o è un (grande) bug in scala ?!

Grazie, Arjun

risposta

11

La seconda nullo si spiega con java.lang.Class#getClassLoader()

Restituisce caricatore di classe per la classe. Alcune implementazioni possono utilizzare null per rappresentare il caricatore di classe bootstrap. Questo metodo restituirà il valore null in tali implementazioni se questa classe è stata caricata dal programma di caricamento classe bootstrap .

Quindi, questo è il motivo per cui classOf[Object].getClassLoader restituisce NULL, è caricato dal classloader di bootstrap (è in rt.jar, più specificamente, è in un vaso che si trova in $ JAVA_HOME/lib).

Il primo null è più difficile da spiegare. Sembra che Scala lasci il classloader di sistema così com'è, e aggiunge solo le opzioni -cp al proprio classloader (ScalaClassLoader in scala/util/ClassLoader.scala).

Utilizzando il seguente:

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

e funzionante con:

$ scala -cp /temp Test 

otteniamo il seguente risultato:

[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 

Così il classloader sistema viene lasciato intatto, ma il Il classloader di Scala recupera gli elementi da -cp.

Morale della trama: non utilizzare il classloader di sistema in Scala se si desidera accedere alle risorse dal classpath.

EDIT: Ok, ho studiato un po 'di più, e scala.pipistrello sta eseguendo la seguente riga di comando (in puro di Windows, accorciata per migliorare la leggibilità)

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

Quindi l'opzione -cp dalla riga di comando viene passato solo come opzione per MainGenericRunner, non java. Credo che, guardando il codice, sotto Unix si possa specificare l'opzione -toolcp su scala per ottenere qualcosa incluso nel classpath java. Qualcosa di simile (totalmente non testata):

$ scala -toolcp /temp Test 

Questa opzione non è disponibile in scala.bat. Il che significa che se si sta lavorando sotto le finestre, dovrete ottenere le risorse utilizzando

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

non riuscivo a trovare un problema nel Scala Lang Issues, ma se è un problema per voi, sollevare un problema e inviare una soluzione. Sono sicuro che saranno entusiasti :-)

EDIT: Ho sollevato questo come problema SI 5062 -toolcp should be available on windows, in the scala.bat e fornito una richiesta di pull per questo github.

0

Da Wikipedia's classloader article:

La classe sistema di codice di carichi caricatore trovato su java.class.path, che mappe alla variabile di sistema CLASSPATH.

Non sono sicuro del secondo valore nullo. Forse qualcun altro può chiarirlo.