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

Это распространенная проблема. Я использую 2 библиотеки A.jar и B.jar, и они зависят от разных версий одного и того же jar.
Допустим, во время выполнения мне нужно ЭТО.xxxjar

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

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

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

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


person mickthompson    schedule 12.10.2009    source источник
comment
Можно ли этого добиться? Как помогает OSGi? Мы снова вводим зависимость от OSGi, которая является накладной в разработке программного обеспечения типичного продукта (особенно для встраиваемых систем)   -  person sskumar86    schedule 17.08.2016


Ответы (5)


«Старый способ», который вы упомянули (и тот, который OSGI, безусловно, использует под капотом), заключается в установке вашего собственного ClassLoader для обеих ветвей ваших зависимостей. Вот как, например, серверы приложений могут запускать как старые, так и новые версии одного и того же приложения внутри одной и той же JVM.

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

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

person Vladimir Dyuzhev    schedule 12.10.2009

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

Взгляните на эту вводную статью о Javaworld Чтобы получить больше информации.

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

person Brian Agnew    schedule 12.10.2009

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


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

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

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


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

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

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

person sfussenegger    schedule 12.10.2009

Чтобы сослаться на базовую «старую» реализацию, проверьте https://github.com/atulsm/ElasticsearchClassLoader.

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

person Atul Soman    schedule 13.02.2016