El cargador de clases Java , parte del Java Runtime Environment , carga dinámicamente clases Java en la máquina virtual Java . [1] Por lo general, las clases solo se cargan bajo demanda . La máquina virtual solo cargará los archivos de clase necesarios para ejecutar el programa. [2] El sistema de ejecución de Java no necesita conocer archivos y sistemas de archivos, ya que esto se delega al cargador de clases.
Una biblioteca de software es una colección de código objeto relacionado . En el lenguaje Java , las bibliotecas suelen estar empaquetadas en archivos JAR . Las bibliotecas pueden contener objetos de diferentes tipos. El tipo de objeto más importante contenido en un archivo Jar es una clase Java . Se puede considerar una clase como una unidad de código con nombre. El cargador de clases es responsable de localizar bibliotecas, leer su contenido y cargar las clases contenidas en las bibliotecas. Esta carga generalmente se realiza "bajo demanda", en el sentido de que no ocurre hasta que el programa llama a la clase. Una clase con un nombre de pila solo puede cargarse una vez mediante un cargador de clases determinado.
Cada clase Java debe ser cargada por un cargador de clases. [3] [4] Además, los programas Java pueden hacer uso de bibliotecas externas (es decir, bibliotecas escritas y proporcionadas por alguien distinto del autor del programa) o pueden estar compuestos, al menos en parte, por varias bibliotecas. .
Cuando se inicia la JVM, se utilizan tres cargadores de clases: [5] [6] [2]
El cargador de clases de arranque carga las bibliotecas principales de Java [fn 1] ubicadas en el directorio <JAVA_HOME>/jre/lib
(o <JAVA_HOME>/jmods>
para Java 9 y superior). Este cargador de clases, que forma parte de la JVM central, está escrito en código nativo. El cargador de clases de arranque no está asociado con ningún ClassLoader
objeto. [2] Por ejemplo, devuelve . [2]StringBuilder.class.getClassLoader()
null
El cargador de clases de extensiones carga el código en los directorios de extensiones ( <JAVA_HOME>/jre/lib/ext
, [5] o cualquier otro directorio especificado por la java.ext.dirs
propiedad del sistema).
El cargador de clases del sistema carga el código encontrado en java.class.path
, que se asigna a la CLASSPATH
variable de entorno .
El cargador de clases Java está escrito en Java. Por lo tanto, es posible crear su propio cargador de clases sin comprender los detalles más finos de la Máquina Virtual Java. Además del cargador de clases Bootstrap, cada cargador de clases Java tiene un cargador de clases principal. [7] El cargador de clases principal se define cuando se crea una instancia de un nuevo cargador de clases o se configura en el cargador de clases predeterminado del sistema de la máquina virtual.
Esto hace posible (por ejemplo):
Los servidores de aplicaciones Jakarta EE (anteriormente Java EE y J2EE) normalmente cargan clases desde un archivo WAR o EAR implementado mediante un árbol de cargadores de clases, aislando la aplicación de otras aplicaciones, pero compartiendo clases entre módulos implementados. Los llamados " contenedores de servlets " normalmente se implementan en términos de múltiples cargadores de clases. [4] [9]
JAR hell es un término similar al DLL hell que se usa para describir las diversas formas en que el proceso de carga de clases puede terminar sin funcionar. [10] Tres formas en que puede ocurrir el infierno JAR son:
La OSGi Alliance especificó (comenzando como JSR 8 en 1998) un marco de modularidad que tiene como objetivo resolver el infierno JAR para las VM actuales y futuras en ME, SE y EE que es ampliamente adoptado. Al utilizar metadatos en el manifiesto JAR , los archivos JAR (llamados paquetes) se conectan por paquete. Los paquetes pueden exportar paquetes, importar paquetes y mantenerlos privados, proporcionando las construcciones básicas de modularidad y gestión de dependencias versionadas.
Para remediar los infernales problemas de JAR, en 2005 se inició un proceso comunitario de Java (JSR 277). La resolución ( Java Platform Module System ) pretendía introducir un nuevo formato de distribución, un esquema de versiones de módulos y un repositorio de módulos común (similar en propósito a Caché de ensamblaje global de Microsoft .NET ). En diciembre de 2008, Sun anunció que JSR 277 estaba en suspenso. [12] El sistema de módulos Java se reinició posteriormente como "proyecto Jigsaw" [13] que se incluyó en Java 9 . Lanzado en 2017, incluye soporte para software modular, denominado "Java Platform Module System", que se controla en el nivel fuente con archivos module-info.java. Sigue una filosofía diferente de la arquitectura OSGi que tiene como objetivo proporcionar modularidad para Java Runtime Environment de una manera compatible con versiones anteriores que utiliza el mecanismo predeterminado de carga de clases que proporciona JRE. Sin embargo, dado que no ofrece la posibilidad de coexistencia controlada de bibliotecas con diferentes versiones, no es adecuado para abordar el problema del infierno JAR. [14]