logo

Cargador de clases en Java

Cargador de clases Java

Java ClassLoader es una clase abstracta. pertenece a un java.lang paquete. Carga clases de diferentes recursos. Java ClassLoader se utiliza para cargar las clases en tiempo de ejecución. En otras palabras, JVM realiza el proceso de vinculación en tiempo de ejecución. Las clases se cargan en la JVM según las necesidades. Si una clase cargada depende de otra clase, esa clase también se carga. Cuando solicitamos cargar una clase, delega la clase a su padre. De esta manera, se mantiene la unicidad en el entorno de ejecución. Es imprescindible ejecutar un programa Java.

ventanas.abrir javascript
Cargador de clases en Java

Java ClassLoader se basa en tres principios: Delegación , Visibilidad , y Unicidad .

    Principio de delegación:Reenvía la solicitud de carga de clases al cargador de clases principal. Solo carga la clase si el padre no encuentra ni carga la clase.Principio de visibilidad:Permite que el cargador de clases secundario vea todas las clases cargadas por el ClassLoader principal. Pero el cargador de clases principal no puede ver las clases cargadas por el cargador de clases secundario.Principio de unicidad:Permite cargar una clase una vez. Se logra mediante el principio de delegación. Garantiza que el ClassLoader secundario no vuelva a cargar la clase, que ya está cargada por el padre.

Tipos de cargador de clases

En Java, cada ClassLoader tiene una ubicación predefinida desde donde carga los archivos de clase. Existen los siguientes tipos de ClassLoader en Java:

Cargador de clases Bootstrap: Carga archivos de clase JDK estándar desde rt.jar y otras clases principales. Es padre de todos los cargadores de clases. No tiene ningún padre. Cuando llamamos a String.class.getClassLoader(), devuelve nulo y cualquier código basado en él arroja NullPointerException. También se le llama Primordial ClassLoader. Carga archivos de clase desde jre/lib/rt.jar. Por ejemplo, clase de paquete java.lang.

Cargador de clases de extensiones: Delega la solicitud de carga de clases a su padre. Si la carga de una clase no tiene éxito, carga las clases desde el directorio jre/lib/ext o cualquier otro directorio como java.ext.dirs. Está implementado por sun.misc.Launcher$ExtClassLoader en JVM.

Cargador de clases del sistema: Carga clases específicas de la aplicación desde la variable de entorno CLASSPATH. Se puede configurar al invocar el programa usando las opciones de línea de comando -cp o classpath. Es hijo de Extension ClassLoader. Está implementado por la clase sun.misc.Launcher$AppClassLoader. Todo Java ClassLoader implementa java.lang.ClassLoader.

Cargador de clases en Java

Cómo funciona ClassLoader en Java

Cuando JVM solicita una clase, invoca un método loadClass() de la clase java.lang.ClassLoader pasando el nombre completo de la clase. El método loadClass() llama al método findLoadedClass() para comprobar si la clase ya se ha cargado o no. Es necesario evitar cargar la clase varias veces.

Si la clase ya está cargada, delega la solicitud al ClassLoader principal para cargar la clase. Si ClassLoader no encuentra la clase, invoca el método findClass() para buscar las clases en el sistema de archivos. El siguiente diagrama muestra cómo ClassLoader carga clases en Java mediante delegación.

Cargador de clases en Java

Supongamos que tenemos una clase Demo.class específica de la aplicación. La solicitud de carga de archivos de esta clase se transfiere a Application ClassLoader. Delega a su ClassLoader de extensión padre. Además, delega en Bootstrap ClassLoader. Bootstrap busca esa clase en rt.jar y como esa clase no está allí. Ahora solicite la transferencia a Extension ClassLoader que busca el directorio jre/lib/ext e intenta ubicar esta clase allí. Si la clase se encuentra allí, Extension ClassLoader carga esa clase. La aplicación ClassLoader nunca carga esa clase. Cuando la extensión ClassLoader no la carga, la aplicación ClaasLoader la carga desde CLASSPATH en Java.

El principio de visibilidad establece que el ClassLoader secundario puede ver la clase cargada por el ClassLoader principal, pero viceversa no es cierto. Significa que si Application ClassLoader carga Demo.class, en tal caso, intentar cargar Demo.class explícitamente usando Extension ClassLoader arroja java.lang.ClassNotFoundException.

De acuerdo con el principio de unicidad, Child ClassLoader no debe volver a cargar una clase cargada por el padre. Por lo tanto, es posible escribir un cargador de clases que viole los principios de delegación y unicidad y cargue la clase por sí solo.

En resumen, el cargador de clases sigue la siguiente regla:

  • Comprueba si la clase ya está cargada.
  • Si la clase no está cargada, solicite al cargador de clases principal que cargue la clase.
  • Si el cargador de clases principal no puede cargar la clase, intente cargarla en este cargador de clases.

Considere el siguiente ejemplo:

 public class Demo { public static void main(String args[]) { System.out.println('How are you?'); } } 

Compile y ejecute el código anterior utilizando el siguiente comando:

 javac Demo.java java -verbose:class Demo 

-detallado:clase: Se utiliza para mostrar la información sobre las clases que carga JVM. Es útil cuando se utiliza el cargador de clases para cargar clases dinámicamente. La siguiente figura muestra el resultado.

Cargador de clases en Java

Podemos observar que las clases de tiempo de ejecución requeridas por la clase de aplicación (Demo) se cargan primero.

Cuando se cargan las clases

Sólo hay dos casos:

  • Cuando se ejecuta el nuevo código de bytes.
  • Cuando el código de bytes hace una referencia estática a una clase. Por ejemplo, salida del sistema .

Carga de clases estática versus dinámica

Las clases se cargan estáticamente con el operador 'nuevo'. La carga dinámica de clases invoca las funciones de un cargador de clases en tiempo de ejecución mediante el método Class.forName().

Diferencia entre loadClass() y Class.forName()

El método loadClass() carga solo la clase pero no inicializa el objeto. Mientras que el método Class.forName() inicializa el objeto después de cargarlo. Por ejemplo, si está utilizando ClassLoader.loadClass() para cargar el controlador JDBC, el cargador de clases no permite cargar el controlador JDBC.

El método java.lang.Class.forName() devuelve el objeto de clase junto con la clase o interfaces con el nombre de cadena dado. Lanza ClassNotFoundException si no se encuentra la clase.

Ejemplo

En este ejemplo, se carga la clase java.lang.String. Imprime el nombre de la clase, el nombre del paquete y los nombres de todos los métodos disponibles de la clase String. Estamos usando Class.forName() en el siguiente ejemplo.

Clase: Representa un objeto Clase que puede ser de cualquier tipo (? es un comodín). El tipo Clase contiene metainformación sobre una clase. Por ejemplo, el tipo de String.class es Clase. Utilice Clase si se desconoce la clase que se está modelando.

getMétodoDeclarado(): Devuelve una matriz que contiene objetos Método que reflejan todos los métodos declarados de la clase o interfaz representada por este objeto Clase, incluidos los métodos públicos, protegidos, de acceso predeterminado (paquete) y privados, pero excluyendo los métodos heredados.

obtenerNombre(): Devuelve el nombre del método representado por este objeto Método, como una Cadena.

 import java.lang.reflect.Method; public class ClassForNameExample { public static void main(String[] args) { try { Class cls = Class.forName('java.lang.String'); System.out.println('Class Name: ' + cls.getName()); System.out.println('Package Name: ' + cls.getPackage()); Method[] methods = cls.getDeclaredMethods(); System.out.println('-----Methods of String class -------------'); for (Method method : methods) { System.out.println(method.getName()); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } 

Producción

 Class Name: java.lang.String Package Name: package java.lang -----Methods of String class ------------- value coder equals length toString hashCode getChars ------ ------ ------ intern isLatin1 checkOffset checkBoundsOffCount checkBoundsBeginEnd access0 access0