Java ClassLoader - Как ссылаться на разные версии банки
-
20-09-2019 - |
Вопрос
Это распространенная проблема. Я использую 2 библиотеки А.Джар а также Б. Джар И они зависят от разных версий одной и той же банки.
Допустим, во время выполнения мне нужно This.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 версию. Который из?
Загрузка только 1 зависимость (последняя версия) означает, что мой код, вероятно, будет добавлять исключения времени выполнения, если библиотеки не совместимы с обратно (существуют ли обратно совместимые библиотеки?).
В любом случае я знаю, что что -то вроде Осги может решить эту проблему.
Мне интересно, как старый способ решить такие проблемы ...
Большое спасибо
Решение
«Старый путь», который вы упомянули (и один Osgi, безусловно, использует под капотом), - это установить свой собственный класс -загрузчик для обеих ветвей ваших зависимостей. Вот как, например, серверы приложений могут запускать как более старые, так и более новые версии одного и того же приложения внутри одного и того же JVM.
Читайте об иерархии класса.
В вашей установке сложная часть - это совместная точка, где встречаются классы из обеих ветвей. Ни одна из ветвей не может использовать классы, загруженные в другой. Способ заставить его работать состоит в том, чтобы убедиться, что только классы, загруженные загрузкой, загрузчика (классы JRE), или класс -загрузчик my.jar передаются в обе ветви.
Другие советы
Осги может решить эту проблему. Пакет OSGI - это не что иное, как банка с дополнительными версиями метаданных. Пакет имеет номер версии и будет подробно описать номера версий (или диапазоны) зависимых банок.
Взгляни на Эта вступительная статья Javavorld Чтобы получить больше информации.
Решить это без OSGI означает необходимость обеспечить вручную, чтобы вы компилировали и работали с совместимыми банками. Как вы обнаружили, это не обязательно тривиальная задача. Поскольку банки не обязательно идентифицируют свои версии, единственный верный способ сделать это для записи/сравнения контрольных сумм или подписей.
Многие библиотеки обратно совместимы. Но не все..
Старый способ - попытаться зависеть только от одной версии.
Вероятно, безопаснее компилировать оба с одной и той же версией (последняя).
По крайней мере, вы получаете ошибки во времени компиляции, а не ошибки времени выполнения.
При необходимости вы можете немного изменить свою библиотеку, которая работает со старой зависимостью ...
Это потребует доступа к источнику ...
Обратите внимание, что совместимость времени компиляции также не гарантирует правильное поведение времени выполнения. Это один шаг, тогда вы можете:
- Прочтите файл WhatsNew для новой версии JAR
- Посмотрите в Интернете для пользователей, сообщающих о проблемах совместимости
- Напишите Junits
- Сравните коды в обеих банках
Как упоминалось KLE, подход по умолчанию зависит от более новой версии. Нет никакой гарантии, но большую часть времени это работает. Вероятно, лучший способ (будучи раздутым) - использовать OSGI, чтобы преодолеть его.
Чтобы направить базовую проверку реализации «Oldway» https://github.com/atulsm/elasticsearchclassloader
Это обеспечивает подход для обработки не совместимых с Backward версиями использования клиента Elasticsearch.