Подтвердить что ты не робот

Java Classloader - как ссылаться на разные версии банки

Это обычная проблема. Я использую 2 библиотеки A.jar и B.jar, и они зависят от разных версий одной и той же банки.
Скажем, что во время выполнения мне нужно THIS.x.x.x.jar

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

Я могу скомпилировать конкретную банку (A.jar/B.jar) против ее зависимости, но во время выполнения я должен загрузить только одну версию. Какой?
Загрузка только 1 зависимости (последняя версия) означает, что мой код, вероятно, будет генерировать исключения во время выполнения, если библиотеки не поддерживают обратную совместимость (есть ли там библиотеки Backward Compatible)?

В любом случае я знаю, что что-то вроде OSGi может решить эту проблему.
Мне интересно, какой старый способ решить такие проблемы...

Спасибо большое

4b9b3361

Ответ 1

"Старый способ", который вы упомянули (и один OSGI, безусловно, использует под капотом), - это установить собственный ClassLoader для обеих ветвей ваших зависимостей. Так, например, серверы приложений могут запускать как старые, так и более новые версии одного и того же приложения внутри одной JVM.

Прочитайте о иерархии загрузчика классов.

В вашей настройке сложной частью является совместная точка, где встречаются классы из обеих ветвей. Ни одна из ветвей не может использовать классы, загруженные в другой. Способ заставить его работать, чтобы только те классы, которые загружались загрузчиком классов (классы JRE) или загрузчиком классов MY.jar, передавались в обе ветки.

Ответ 2

OSGi может решить эту проблему. Комплект OSGi представляет собой не что иное, как банку с дополнительными метаданными, детализирующими версии. Пакет имеет номер версии и будет содержать номера версий (или диапазонов) зависимых банок.

Посмотрите эту вводную статью Javaworld для получения дополнительной информации.

Чтобы решить эту проблему без OSGi, вам необходимо вручную обеспечить компиляцию и запуск с совместимыми банками. Как вы обнаружили, это не обязательно тривиальная задача. Поскольку банки не обязательно идентифицируют свои версии, это единственный верный способ сделать это для записи/сравнения контрольных сумм или подписей.

Ответ 3

Многие библиотеки обратно совместимы. Но не все..


Старый способ - попытаться зависеть только от одной версии.

Вероятно, более безопасно компилировать обе версии с той же версией (последняя).
По крайней мере, вы получаете ошибки времени компиляции, а не ошибки времени выполнения.

При необходимости вы можете немного изменить свою библиотеку, которая работает со старой зависимостью...
Для этого потребуется доступ к источнику...


Обратите внимание, что совместимость во времени компиляции также не гарантирует правильное поведение во время выполнения. Это один шаг, затем вы можете:

  • прочитайте файл WhatsNew для новой версии jar
  • посмотрите в Интернете для пользователей, сообщающих о проблемах совместимости.
  • написать JUnits
  • сравнить коды в обеих банках

Ответ 4

Как упоминалось KLE, подход по умолчанию должен зависеть от более новой версии. Нет никакой гарантии, но большую часть времени это работает. Вероятно, лучший способ (будучи раздутым) использовать OSGI, чтобы преодолеть это.

Ответ 5

Чтобы передать базовую проверку реализации "старого пути" https://github.com/atulsm/ElasticsearchClassLoader

Это обеспечивает подход к обработке не-обратных совместимых версий использования клиента elasticsearch.