Что происходит, когда двум фреймворкам Java нужен третий, но каждый из них нуждается в другой версии третьего?

В моем проекте Java я использую две разные структуры (например, A.jar и B.jar), и для обоих из них требуется одна общая структура (скажем, Log4j.jar), но в двух разных версиях. Как это обрабатывается Java, если для инфраструктуры A требуется Log4J v1.1, а B - Log4j v1.2? Будет ли это причиной какого-либо конфликта/ошибки или будет каким-то образом (как?) Разрешено?

Если это не вызовет конфликт/ошибку (мой проект может быть скомпилирован и запущен) - могу ли я использовать любую версию Log4j самостоятельно в этом проекте? Или я вынужден выбрать более низкий/более высокий номер версии Log4j?

Обновление:, чтобы быть более конкретным... Что делать, если какая-то часть API-интерфейса Log4j изменилась в версии 1.2 (скажем, изменилась одна сигнатура doIt() одного метода), и оба A и B вызывают doIt. Что будет? Будет ли мой проект работать? Повредет ли он при первом использовании doIt? Какую версию Log4j я должен поставить в classpath - v1.2 или оба?

Ответы

Ответ 1

Java не поддерживает управление несколькими версиями одного и того же фрагмента кода, то есть вы можете использовать не более одной версии в пределах одной JVM (с загрузчиком класса по умолчанию). Тем не менее, вопрос оплаты 1705720, в котором есть несколько ответов, указывающих возможные пути достижения этого (OSGi или пользовательские загрузчики классов).

Но я сомневаюсь, что это стоит того, так как несколько версий log4j не требуются вашим кодом напрямую. В этом случае я бы посоветовал сначала начать использовать новую версию log4j (v1.2) и проверить, вызовет ли она какие-либо проблемы для фреймворка A. Если это вызывает конфликт, то возвратитесь к log4j v1.1 и снова проверьте. Если вам действительно не повезло, тогда вам нужно загрязнить руки...

Обновить: для вашего конкретного описания нет способа использовать либо log4j v1.1, либо v1.2, так как для каждой рамки A и B требуется различная подпись. Вы должны катить свою версию любого из log4j или рамки A или B.

Ответ 2

В схеме загрузки с плоским классом поддержка поддержки версий библиотеки отсутствует. Вам нужно использовать самую последнюю версию библиотеки и удалить другие версии из пути к классам.

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


Edit:

Что делать, если какая-то часть API Log4j изменилась в версии 1.2 (скажем, изменилась одна сигнатура doIt()), и оба A и B вызывают doIt. Что случится? Будет ли мой проект работать? Будет ли он сбой при первом использовании doIt?

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

Какую версию Log4j я должен поставить в classpath - v1.2 или оба?

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

Ответ 3

Если ваш удачный выбор одной версии стороннего баннера будет работать. В конце концов, нужен контейнер, который понимает и позволяет управлять версиями всех компонентов, что-то вроде OSGI.

Ответ 4

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

Оптимальным решением будет получение последних версий как A, так и B, где оба используют последние общие библиотеки