jueves, 7 de febrero de 2013

El Infiernos de los JAR


Ultimamente he dedicado algo de tiempo a profundizar en OSGI. Ya partía de una idea básica sobre la plataforma, pero quería algo de conocimiento práctico que me llevase a tener algo más de confianza si tenía que usarlo en un futuro. ¿Y por qué hablo de OSGI si titulo al post "El infierno de los JAR"? Pues realmente porque está muy relacionado, y porque me ha encantado encontrarme con una buena explicación de los ClassLoader buscando información sobre OSGI (realmente la justificación de OSGI biene dada por las definiciencias de la carga de clases).

1. Como funcionan los cargadores en JRE.


Los cargadores forman una estructura jerárquica donde encontramos que todo cargador puede tener un padre y sólo un padre. Esto en el caso más complejo nos puede dar una extructura de árbol, y en el caso más sencillo una lista de cargadores (Al final todo hilo de una JVM tiene una lista de cargadores. Esta se obtendría recorriendo en profundidad el arbol). Podemos dibujar una jerarquía de clargadores en donde aparecerán cuatro tipo de cargadores:
  • Bootstrap class loader
    El cargador de los elementos nativos de Java.
  • Extension class loader
    El cargador de los elementos situados en el directorio libext (por ejemplo los paquetes que empiecen por java y javax).
  • Application class loader
    El cargador de los elementos del classpath.
  • CustomClassLoader
    Si nos aventuramos podemos diseñar nuestro propio cargador para habilitar fuentes extra.

2. Problema


Los JAR ni son módulos, ni son una buena solución para diseñar módulos, porque:
  • No existe el concepto de JAR en tiempo de ejecución.
  • No pueden indicar sus dependencias.
  • No están versionados (no podemos cargar dos versiones de una libreria).
  • No existe un buen mecanismo de encapsulado a nivel de JAR (el control de acceso se limita a nivel de clase y paquete).

3. Consecuencia


Si se incluyen dos versiones de una libreria la carga de las clases dependerá del orden en el que aparezcan los JAR en el classpath. En el peor de los casos podrían cargarse el segundo JAR de forma parcial. En este último caso las clases del JAR semioculto referenciarian a instancias de clases cuya definición no se corresponde con la esperada.



En el caso de jerarquías complejas de classloader (como en los servidores de aplicaciones) esto suele producir que los modulos no se compartan. Cada aplicación carga todos los elementos necesarios para su funcionamiento, siendo a efectos practicos sistemas independientes y completos en lugar de modulos interrelacionados.


4.Solución


Pues OSGI al rescate. OSGI cambia la estructura de los classloader permitiendo dibujar grafos. También define una serie de entradas en el fichero metainfo.mf para corregir las carencias de los JAR convirtiéndolos en módulos de pleno derecho:
  • Nombre del módulo
  • Versión del módulo
  • Definiciones del módulo (exports)
  • Dependencias (imports)

No hay comentarios:

Publicar un comentario