¿Qué es un Java ClassLoader?

174

En pocas oraciones simples, ¿qué es un Java ClassLoader, cuándo se usa y por qué?

OK, leí un artículo wiki. ClassLoader carga clases. OKAY. Entonces, si incluyo archivos jar e importo, un ClassLoader hace el trabajo.

¿Por qué debería molestarme con este ClassLoader? Nunca lo he usado y no sabía que existía.

La pregunta es, ¿por qué existe la clase ClassLoader? Y también, ¿cómo lo usas en la práctica? (Existen casos, lo sé).

EugeneP
fuente
Obtendrá mejores resultados si reduce su pregunta, por ejemplo, al señalar una parte específica que no comprende, cómo se relaciona con algún otro idioma con el que esté familiarizado, etc.
JRL
75
Esta es una pregunta completamente razonable, cuando se ve desde la perspectiva de alguien que busca unas pocas oraciones simples para explicar el concepto
oxbow_lakes
Este video puede ser de interés: ¿Realmente obtienes cargadores de clase?
asmaier

Respuestas:

231

Tomado de este bonito tutorial de Sun:

Motivación

Las aplicaciones escritas en lenguajes de programación compilados estáticamente, como C y C ++, se compilan en instrucciones nativas específicas de la máquina y se guardan como un archivo ejecutable. El proceso de combinar el código en un código nativo ejecutable se llama vinculación: la fusión de código compilado por separado con código de biblioteca compartida para crear una aplicación ejecutable. Esto es diferente en lenguajes de programación compilados dinámicamente como Java. En Java, los archivos .class generados por el compilador de Java permanecen tal cual hasta que se cargan en la máquina virtual Java (JVM); en otras palabras, el proceso de vinculación lo realiza la JVM en tiempo de ejecución. Las clases se cargan en la JVM "según sea necesario". Y cuando una clase cargada depende de otra clase, entonces esa clase también se carga.

Cuando se inicia una aplicación Java, la primera clase que se ejecuta (o el punto de entrada a la aplicación) es la que tiene un método público de vacío estático llamado main (). Esta clase generalmente tiene referencias a otras clases, y todos los intentos de cargar las clases referenciadas son realizados por el cargador de clases.

Para tener una idea de esta carga recursiva de clases, así como la idea de carga de clases en general, considere la siguiente clase simple:

public class HelloApp {
   public static void main(String argv[]) {
      System.out.println("Aloha! Hello and Bye");
   }
}

Si ejecuta esta clase especificando la opción de línea de comandos -verbose: class, de modo que imprima las clases que se están cargando, obtendrá un resultado similar al siguiente. Tenga en cuenta que esto es solo una salida parcial ya que la lista es demasiado larga para mostrar aquí.

prmpt>java -verbose:class HelloApp



[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]

Como puede ver, las clases de tiempo de ejecución Java requeridas por la clase de aplicación (HelloApp) se cargan primero.

Cargadores de clases en la plataforma Java 2

El lenguaje de programación Java sigue evolucionando para facilitar la vida de los desarrolladores de aplicaciones todos los días. Esto se logra al proporcionar API que simplifican su vida al permitirle concentrarse en la lógica empresarial en lugar de los detalles de implementación de los mecanismos fundamentales. Esto es evidente por el cambio reciente de J2SE 1.5 a J2SE 5.0 para reflejar la madurez de la plataforma Java.

A partir de JDK 1.2, un cargador de clases de arranque integrado en la JVM es responsable de cargar las clases del tiempo de ejecución de Java. Este cargador de clases solo carga las clases que se encuentran en el classpath de arranque, y dado que estas son clases confiables, el proceso de validación no se realiza como para las clases no confiables. Además del cargador de clases bootstrap, la JVM tiene un cargador de clases de extensión responsable de cargar clases desde API de extensión estándar, y un cargador de clases de sistema que carga clases desde una ruta de clase general, así como sus clases de aplicación.

Como hay más de un cargador de clases, se representan en un árbol cuya raíz es el cargador de clases bootstrap. Cada cargador de clases tiene una referencia a su cargador de clases padre. Cuando se le pide a un cargador de clases que cargue una clase, consulta a su cargador de clases padre antes de intentar cargar el elemento en sí. El padre a su vez consulta a su padre, y así sucesivamente. Por lo tanto, solo después de que todos los cargadores de clases ancestrales no puedan encontrar la clase, el cargador de clases actual se involucra. En otras palabras, se utiliza un modelo de delegación.

La clase java.lang.ClassLoader

La java.lang.ClassLoaderes una clase abstracta que puede ser subclasificada por aplicaciones que necesitan extender la manera en que la JVM carga dinámicamente las clases. Los constructores en java.lang.ClassLoader(y sus subclases) le permiten especificar un padre cuando crea una instancia de un nuevo cargador de clases. Si no especifica explícitamente un elemento primario, el cargador de clases del sistema de la máquina virtual se asignará como elemento primario predeterminado. En otras palabras, la clase ClassLoader usa un modelo de delegación para buscar clases y recursos. Por lo tanto, cada instancia de ClassLoader tiene un cargador de clases padre asociado, de modo que cuando se le solicita que encuentre una clase o recursos, la tarea se delega a su cargador de clases padre antes de intentar encontrar la clase o el recurso en sí. El loadClass()método de ClassLoader realiza las siguientes tareas, en orden, cuando se llama para cargar una clase:

Si una clase ya se ha cargado, la devuelve. De lo contrario, delega la búsqueda de la nueva clase al cargador de clases padre. Si el cargador de clases padre no encuentra la clase, loadClass()llama al método findClass()para buscar y cargar la clase. El finalClass()método busca la clase en el cargador de clases actual si el cargador de clases padre no encontró la clase.


Hay más en el artículo original, que también le muestra cómo implementar sus propios cargadores de clases de red, que responde a su pregunta de por qué (y cómo). Ver también los documentos API .

JRL
fuente
47

La mayoría de los desarrolladores de Java nunca necesitarán usar explícitamente cargadores de clases (excepto para cargar recursos para que todavía funcione cuando están agrupados en JAR), y mucho menos escribir los suyos.

Los ClassLoaders se usan en sistemas grandes y aplicaciones de servidor para hacer cosas como:

  • Modularice un sistema y cargue, descargue y actualice módulos en tiempo de ejecución
  • Utilice diferentes versiones de una biblioteca API (por ejemplo, un analizador XML) en paralelo
  • Aísle diferentes aplicaciones que se ejecutan dentro de la misma JVM (asegurándose de que no interfieran entre sí, por ejemplo, a través de variables estáticas)
Michael Borgwardt
fuente
29

La pregunta es "¿Por qué debería uno molestar a esta clase de ClassLoader?"

Bueno, sobre todo para que puedas arreglar las cosas si salen mal :-).

Es cierto, siempre y cuando solo escriba una aplicación, la compile en un JAR y tal vez incluya algunos JAR de biblioteca adicionales, no necesita saber acerca de los cargadores de clases, simplemente funcionará.

Aún así, es útil saber un poco sobre los cargadores de clases y la carga de clases para comprender mejor lo que sucede detrás de escena. Como ejemplo, los "inicializadores estáticos" se ejecutarán cuando se cargue una clase, por lo que para saber cuándo se ejecutarán, debe saber cómo decide el cargador de clases cuándo cargarlos.

también ... ¿cómo lo usas en la práctica?

Para casos simples, no los necesita. Sin embargo, si necesita cargar código dinámicamente en tiempo de ejecución con un control explícito de dónde proviene (por ejemplo, cargar a través de una red, cargar complementos no disponibles en el momento de la compilación, etc.), es posible que deba hacer más. Entonces puede, por ejemplo, escribir su propio cargador de clases. Vea las otras respuestas para enlaces.

sleske
fuente
14

ClassLoaderen Java es una clase que se usa para cargar archivos de clase en Java. El código Java es compilado en un archivo de clase porjavac y JVM ejecuta el programa Java ejecutando códigos de bytes escritos en el archivo de clase.

ClassLoader es responsable de cargar archivos de clase desde el sistema de archivos, la red o cualquier otra fuente. Hay tres cargadores de clases predeterminados utilizados en Java, Bootstrap , Extension y System o Application class loader.

ClassLoader


Cómo funciona ClassLoader

## Interacción de ClassLoader con JVM ingrese la descripción de la imagen aquí

Más @ amazon.es

roottraveller
fuente
6

Los cargadores de clase son un componente funcional de JVM, que carga datos de clase desde el archivo '.class' o desde la red hasta el área de método en el montón.

Parece una parte integral de la JVM, pero como usuario final de Java, ¿por qué debería preocuparme? Aquí es por qué:

Cada cargador de clases tiene su propio espacio de nombres y las clases invocadas por un cargador de clases en particular entran en su espacio de nombres.

Las clases invocadas por dos cargadores de clases diferentes no tendrán visibilidad entre sí, lo que dará como resultado una mayor seguridad.

El mecanismo de delegación padre-hijo del cargador de clases garantiza que las clases api java nunca puedan ser pirateadas por código no autorizado.

Para más detalles mira aquí

bitan
fuente
1

Los cargadores de clases son jerárquicos. Las clases se introducen en la JVM ya que se hace referencia a ellas por nombre en una clase que ya se está ejecutando en la JVM.

¿Cómo se cargó la primera clase?
La primera clase se carga con la ayuda destatic main() método declarado en su clase. Todas las clases cargadas posteriormente son cargadas por las clases, que ya están cargadas y en ejecución.

Un cargador de clases crea un espacio de nombres. Todas las JVM incluyen al menos un cargador de clases que está incrustado dentro de la JVM llamado cargador de clases primordial (o bootstrap) . Eso es una cosa, y veremos cargadores de clases no primordiales. La JVM tiene ganchos para permitir que los cargadores de clases definidos por el usuario se usen en lugar del cargador de clases primordial. Aquí están los cargadores de clases creados por la JVM.

Bootstrap (primordial) Este cargador de clases no se puede volver a cargar. Carga clases internas JDK, paquetes java. * (Generalmente carga rt.jar e i18n.jar). Extensiones Este cargador de clases no se puede volver a cargar. Carga archivos jar del directorio de extensiones JDK (generalmente lib / ext de JRE). Sistema Este cargador de clases no se puede volver a cargar. Carga clases desde la ruta de clase del sistema.

http://www.sbalasani.com/2015/01/java-class-loaders.html

Srinivas Balasani
fuente
1

Cuando pregunta por qué existe la clase ClassLoader, la razón es bastante simple: es la clase responsable de encontrar y cargar archivos de clase en tiempo de ejecución .

Vamos a elaborarlo.

En JVM, cada clase es cargada por alguna instancia de java.lang.ClassLoader. Cada vez que un java <classname>comando de inicio de programa Java habitual inicia una nueva JVM , el primer paso es cargar todas las clases clave en la memoria necesarias para un funcionamiento adecuado java.lang.Objecty otras clases de tiempo de ejecución ( rt.jar).

Ahora, en realidad hay 3 partes en ClassLoader:

  • El BootstrapClassLoaderes responsable de hacer que estas clases estén disponibles, es decir, cargar estas clases en la memoria.

  • La siguiente tarea es cargar cualquier biblioteca externa / JAR en la memoria para que la aplicación funcione correctamente. El ExtClassLoaderes responsable de esta tarea. Este cargador de clases es responsable de cargar todos los archivos .jar mencionados en la ruta java.ext.dirs.

  • El tercer y el principal cargador de clase importante es el AppClassLoader. El cargador de clases de la aplicación es responsable de cargar los archivos de clase mencionados en la propiedad del sistema java.class.path.

También es importante tener en cuenta que las implementaciones predeterminadas de ClassLoader podrían anularse, permitiéndole personalizar la JVM de maneras útiles e interesantes, permitiéndole redefinir completamente cómo se introducen los archivos de clase en el sistema.

ingrese la descripción de la imagen aquí

Compruébelo para obtener más información sobre Java Class Loader .

Johnny
fuente