java jar dependencies classloader versions

Java Classloader: cómo hacer referencia a diferentes versiones de un jar



dependencies versions (5)

Este es un problema común. Estoy usando 2 bibliotecas A.jar y B.jar y estas dependen de diferentes versiones del mismo jar.
Digamos que en el tiempo de ejecución necesito ESTO.xxxjar

MY.jar -> A.jar -> THIS.1.0.0.jar -> B.jar -> C.jar -> THIS.5.0.0.jar

Puedo compilar el jar específico (A.jar / B.jar) contra su dependencia pero en el tiempo de ejecución tengo que cargar solo 1 versión. ¿Cúal?
Cargar solo 1 dependencia (la última versión) significa que mi código probablemente arrojará excepciones de tiempo de ejecución si las bibliotecas no son compatibles con versiones anteriores (¿hay bibliotecas compatibles con versiones anteriores?).

De todos modos, sé que algo como OSGi puede solucionar este problema.
Me pregunto cuál es la forma antigua de solucionar este tipo de problemas ...

Muchas gracias


Como lo menciona KLE, el enfoque predeterminado es depender de la versión más reciente. No hay garantía, pero la mayoría de las veces esto funciona. Probablemente la mejor manera (aunque esté hinchada) es usar OSGI para superarlo.


La "forma antigua" que mencionó (y la única que OSGI usa debajo del capó) es instalar su propio ClassLoader para las dos ramas de sus dependencias. Así es como, por ejemplo, los servidores de aplicaciones pueden ejecutar versiones anteriores y nuevas de la misma aplicación dentro de la misma JVM.

Lea acerca de la jerarquía del cargador de clases.

En su configuración, la parte difícil es el punto conjunto, donde se reúnen las clases de ambas ramas. Ninguna de las ramas puede usar clases cargadas en otra. La forma de hacerlo funcionar es asegurarse de que solo las clases cargadas por el cargador de clases de arranque (clases JRE) o el cargador de clases de MY.jar se transmitan a ambas ramas.


Muchas bibliotecas son compatibles con versiones anteriores. Pero no todos..

La forma antigua es tratar de depender de una sola versión.

Probablemente sea más seguro compilar ambos con la misma versión (la última).
Al menos obtienes errores en tiempo de compilación, en lugar de errores en tiempo de ejecución.

Si es necesario, puede modificar un poco su biblioteca que funciona con la antigua dependencia ...
Esto requeriría acceso a la fuente ...

Tenga en cuenta que la compatibilidad en tiempo de compilación tampoco garantizará el comportamiento correcto del tiempo de ejecución. Es un paso, entonces puedes:

  • lee el archivo de WhatsNew para la nueva versión del jar
  • Busque en Internet los usuarios que informen sobre problemas de compatibilidad.
  • escribe JUnits
  • compara los códigos en ambos frascos

OSGi puede solucionar este problema. Un paquete OSGi no es más que un jar con metadatos adicionales que detallan versiones. Un paquete tiene un número de versión y detallará los números de versión (o rangos) de los tarros dependientes.

Echa un vistazo a este artículo introductorio de Javaworld para obtener más información.

Resolver esto sin OSGi significa tener que garantizar manualmente que compile y ejecute con archivos jar compatibles. Como has descubierto, eso no es necesariamente una tarea trivial. Dado que los frascos no necesariamente identifican sus versiones, es la única forma segura de hacer esto para registrar / comparar sumas de comprobación o firmas.


Para consultar una comprobación de implementación básica "antigua" https://github.com/atulsm/ElasticsearchClassLoader

Esto proporciona un enfoque para manejar versiones no compatibles con versiones anteriores del uso del cliente de elasticsearch.