2011-10-06 13 views
9

Por favor considere el siguiente programa de prueba (usando Scala 2.9.0.1)cargadores de clases Scala confusión

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

puedo compilar y ejecutarlo con "cp/tmp" que contiene un archivo "toto", y consigo el siguiente resultado:

null 
file:/tmp/toto 
null 

=> el cargador de clases del sistema no contiene la ruta de clase

=> la clase Object no tiene cargador de clases!

¿Me falta algo allí o es un gran error en scala?

Gracias, Arjun

Respuesta

11

El segundo nula se explica por java.lang.Class#getClassLoader()

Devuelve el cargador de clases para la clase. Algunas implementaciones pueden usar null para representar el cargador de clase bootstrap. Este método devolverá nulo en tales implementaciones si esta clase fue cargada por el cargador de clase bootstrap .

Por lo tanto, esta es la razón por classOf[Object].getClassLoader vuelve nulo, que se carga por el cargador de clases de arranque (está en rt.jar, más específicamente, es en un frasco que está en $ JAVA_HOME/lib).

El primer nulo es más difícil de explicar. Parece que Scala abandona el cargador de clases del sistema tal como está, y solo agrega las opciones -cp a su propio cargador de clases (ScalaClassLoader en scala/util/ClassLoader.scala).

Usando el siguiente:

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

y ejecutarlo con:

$ scala -cp /temp Test 

obtenemos el siguiente resultado:

[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 

Así que el cargador de clases del sistema se deja intacto, pero el El clasificador de Scala obtiene los elementos de -cp agregados a él.

Moraleja de la historia: no use el cargador de clases del sistema en Scala si desea acceder a los recursos del classpath.

EDITAR: Ok, he investigado esto un poco más, y scala.bate está ejecutando la línea de comando siguiente (bajo pura de Windows, abreviada para facilitar la lectura)

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

Así que la opción -cp desde la línea de comandos se pasa como una opción para MainGenericRunner, no el java. Creo que al mirar el código, bajo Unix puedes especificar la opción -toolcp en scala para obtener algo incluido en el classpath de java. Algo así como (totalmente no probado):

$ scala -toolcp /temp Test 

Esta opción no está disponible en scala.bat. Lo que significa que si está trabajando en Windows, tendrá que obtener los recursos usando

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

no pude encontrar un problema en el Scala Lang Issues, pero si es un problema para usted, plantear un problema y se somete un arreglo. Estoy seguro de que estarán encantados :-)

EDITAR: He planteado esto como problema SI 5062 -toolcp should be available on windows, in the scala.bat, y proporcioné una solicitud de extracción en github.

0

De Wikipedia's classloader article:

La clase de sistema de código carga del cargador se encuentra en java.class.path, que mapas a la variable CLASSPATH del sistema.

No estoy seguro acerca del segundo nulo sin embargo. Quizás alguien más pueda aclarar eso.

Cuestiones relacionadas