Cada clase usará su propio cargador de clases para cargar otras clases. Así que si ClassA.class
las referencias ClassB.class
a continuación, ClassB
tiene que estar en la ruta de clase del cargador de clases deClassA
, o de sus padres.
El cargador de clases de contexto de hilo es el cargador de clases actual para el hilo actual. Se puede crear un objeto a partir de una clase ClassLoaderC
y luego pasarlo a un hilo propiedad de ClassLoaderD
. En este caso, el objeto debe usarse Thread.currentThread().getContextClassLoader()
directamente si desea cargar recursos que no están disponibles en su propio cargador de clases.
ClassB
debe estar en el classpath delClassA
cargador de (oClassA
los padres del cargador)? ¿No es posible queClassA
el cargador se anuleloadClass()
, de modo que se pueda cargar con éxitoClassB
incluso cuandoClassB
no está en su classpath?ClassA.class
referenciasClassB.class
"?Esto no responde a la pregunta original, pero como la pregunta está altamente clasificada y vinculada a cualquier
ContextClassLoader
consulta, creo que es importante responder la pregunta relacionada de cuándo se debe usar el cargador de clases de contexto. Respuesta corta: ¡ nunca use el cargador de clases de contexto ! Pero configúralo engetClass().getClassLoader()
cuando tenga que llamar a un método al que le falta unClassLoader
parámetro.Cuando el código de una clase pide cargar otra clase, el cargador de clases correcto para usar es el mismo cargador de clases que la clase que llama (es decir,
getClass().getClassLoader()
). Así es como funcionan las cosas el 99.9% del tiempo porque esto es lo que hace la JVM la primera vez que construye una instancia de una nueva clase, invoca un método estático o accede a un campo estático.Cuando desee crear una clase utilizando la reflexión (como al deserializar o cargar una clase con nombre configurable), la biblioteca que hace la reflexión siempre debe preguntarle a la aplicación qué cargador de clase usar, al recibir el
ClassLoader
parámetro como parte de la aplicación. La aplicación (que conoce todas las clases que necesitan construirse) debería pasarlagetClass().getClassLoader()
.Cualquier otra forma de obtener un cargador de clases es incorrecta. Si una biblioteca usa hacks como
Thread.getContextClassLoader()
,sun.misc.VM.latestUserDefinedLoader()
osun.reflect.Reflection.getCallerClass()
es un error causado por una deficiencia en la API. Básicamente,Thread.getContextClassLoader()
existe solo porque quien diseñó laObjectInputStream
API olvidó aceptar elClassLoader
como parámetro, y este error ha perseguido a la comunidad Java hasta el día de hoy.Dicho esto, muchas clases de JDK usan uno de los pocos hacks para adivinar algún cargador de clases para usar. Algunos usan el
ContextClassLoader
(que falla cuando ejecuta diferentes aplicaciones en un grupo de subprocesos compartido, o cuando abandona elContextClassLoader null
), algunos recorren la pila (que falla cuando el llamante directo de la clase es una biblioteca), algunos usan el cargador de clases del sistema (lo cual está bien, siempre que esté documentado para usar solo clases en elCLASSPATH
) o cargador de clases bootstrap, y algunos usan una combinación impredecible de las técnicas anteriores (lo que solo hace las cosas más confusas). Esto ha resultado en mucho llanto y crujir de dientes.Cuando utilice una API de este tipo, primero, trate de encontrar una sobrecarga del método que acepte el cargador de clases como parámetro . Si no hay un método razonable, intente configurar
ContextClassLoader
antes de la llamada API (y restablecerlo después):fuente
Hay un artículo en javaworld.com que explica la diferencia => Qué ClassLoader debe usar
(1)
(2) de la misma fuente:
fuente
bootstrap
está configurando el cargador de clases padre como el cargador de clases de contexto, sino elsystem
cargador de clases classpath hijo con el queThread
se está configurando. LasJNDI
clases se aseguran de usarThread.currentThread().getContextClassLoader()
para cargar las clases de implementación JNDI disponibles en el classpath.Agregando a la respuesta @David Roussel, las clases pueden ser cargadas por múltiples cargadores de clases.
Vamos a entender cómo funciona el cargador de clases .
Del blog de javin paul en javarevisited:
ClassLoader
Sigue tres principios.Principio de delegación
Bootstrap ClassLoader es responsable de cargar archivos de clase JDK estándar desde rt.jar y es el padre de todos los cargadores de clases en Java. El cargador de clases Bootstrap no tiene padres.
Extension ClassLoader delega la solicitud de carga de clase a su principal, Bootstrap y, si no tiene éxito, carga el formulario jre / lib / ext o cualquier otro directorio señalado por la propiedad del sistema java.ext.dirs
El cargador de clases de sistema o aplicación es responsable de cargar las clases específicas de la aplicación desde la variable de entorno CLASSPATH, la opción de línea de comando -classpath o -cp, el atributo Class-Path del archivo de manifiesto dentro de JAR.
Application class loader es un elemento secundario de Extension ClassLoader y está implementado por
sun.misc.Launcher$AppClassLoader
clase.NOTA: Excepto el cargador de clases Bootstrap , que se implementa en lenguaje nativo principalmente en C, todos los cargadores de clases Java se implementan usando
java.lang.ClassLoader
.Principio de visibilidad
Principio de singularidad
fuente