Что происходит, когда двум фреймворкам 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, где оба используют последние общие библиотеки