Поделиться через


Устранение конфликтов версий зависимостей

В этой статье описаны конфликты версий зависимостей и способы их устранения.

Azure клиентские библиотеки для Java зависят от популярных сторонних библиотек, таких как следующие:

Многие Java приложения и платформы используют эти библиотеки напрямую или транзитивно, что приводит к конфликтам version. Менеджеры зависимостей, такие как Maven и Gradle, управляют всеми зависимостями, чтобы в classpath была только одна версия каждой зависимости. Однако не гарантируется, что разрешенная версия зависимостей совместима со всеми потребителями этой зависимости в приложении. Дополнительные сведения см. в разделе "Общие сведения о механизме зависимостей " в документации Maven и разрешении зависимостей в документации по Gradle.

Несовместимость API прямых зависимостей приводит к ошибкам компиляции. Несовместимость алмазной зависимости обычно приводит к сбоям среды выполнения, таким как NoClassDefFoundError, NoSuchMethodError или другая ошибка связывания. Не все библиотеки строго следуют семантической версии и критические изменения иногда происходят в одной основной версии.

Диагностика проблем с несоответствием версий

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

Использование Azure SDK для средства сборки Java

Средство сборки Azure SDK для Java, описанное в Начале работы с Azure SDK и Apache Maven, помогает выявлять часто встречающиеся проблемы. Мы рекомендуем добавить это средство сборки в проект и запустить его, добавив целевой azure:run объект Maven в обычный процесс сборки. С помощью соответствующей конфигурации можно выявлять и устранять конфликты зависимостей более упреждающим образом, прежде чем они становятся проблемами во время выполнения.

Просмотр дерева зависимостей

Запустите mvn dependency:tree или gradle dependencies --scan, чтобы отобразить полное дерево зависимостей для вашего приложения с номерами версий. mvn dependency:tree -Dverbose предоставляет дополнительные сведения, но может вводить в заблуждение. Дополнительные сведения см. в разделе "Дерево зависимостей Apache Maven " в документации Maven. Для каждой библиотеки, подозреваемой в конфликте версий, обратите внимание на его номер версии и определите, какие компоненты зависят от него.

Разрешение зависимостей в средах разработки и рабочей среды может работать по-разному. Плагины IDE для Apache Spark, Apache Flink, Databricks требуют дополнительной настройки для пользовательских зависимостей. Они также могут привести собственные версии Azure клиентских библиотек или общих компонентов. Дополнительные сведения см. в следующих статьях:

Дополнительные сведения о разрешении конфликтов в таких средах см. в разделе "Создание Fat JAR" далее в этой статье.

Настройка Azure Functions

Версия внутренней зависимости в Azure Functions, работающих только на Java 8, имеет приоритет над версией, предоставленной пользователем. Эта зависимость вызывает конфликты версий, особенно с Jackson, Netty и Reactor.

Чтобы решить эту проблему, установите значение переменной среды FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBS на true или 1. Обязательно обновите средства функций Azure (версии 2 или версии 3) до последней версии.

Примечание.

Эта конфигурация применяется только к функциям Azure, запускаемым на Java 8, функции, использующие Java 11, не требуют специальной конфигурации.

Настройка Apache Spark

Azure SDK для Java поддерживает несколько версий Джексона, но иногда могут возникнуть проблемы в зависимости от инструмента сборки и его упорядочивания зависимостей. Хорошим примером этой проблемы является Apache Spark версии 3.0.0 и более поздней версии, которая зависит от Джексона 2.10. Хотя он совместим с Azure SDK для Java, разработчики часто обнаруживают, что более поздняя версия Джексона используется вместо этого, что приводит к несовместимости. Чтобы устранить эту проблему, следует закрепить определенную версию Джексона (совместимую с Spark). Дополнительные сведения см. в разделе «Поддержка нескольких версий Джексона» в этой статье.

Если вы используете более ранние версии Spark, или если другая библиотека требует еще более раннюю версию Jackson, которую не поддерживает Azure SDK для Java, продолжайте читать эту статью для возможных шагов по устранению ошибок.

Определение версии среды выполнения Jackson

В Azure Core 1.21.0 мы добавили обнаружение среды выполнения и улучшенную диагностику версии среды выполнения Джексона.

Если вы видите LinkageError (или любой из его подклассов), связанных с API Джексона, проанализируйте сообщение об исключении для получения сведений о версии среды выполнения. Например: com.azure.core.implementation.jackson.JacksonVersionMismatchError: com/fasterxml/jackson/databind/cfg/MapperBuilder Package versions: jackson-annotations=2.9.0, jackson-core=2.9.0, jackson-databind=2.9.0, jackson-dataformat-xml=2.9.0, jackson-datatype-jsr310=2.9.0, azure-core=1.19.0-beta.2

Найдите журналы предупреждений и ошибок от JacksonVersion. Дополнительные сведения см. в разделе Настройка журнала в Azure SDK для Java. Например: [main] ERROR com.azure.core.implementation.jackson.JacksonVersion - Version '2.9.0' of package 'jackson-core' is not supported (too old), please upgrade.

Примечание.

Убедитесь, что все пакеты Jackson имеют одинаковую версию.

Список пакетов, используемых Azure SDK и поддерживаемых версиях Джексона, см. в разделе Support для нескольких версий Джексона.

Устранение проблем с несоответствием версий

В следующих разделах описывается устранение проблем с несоответствием версий.

Используйте Azure SDK BOM

Используйте последнюю стабильную Azure SDK BOM и не указывайте версии Azure SDK и зависимостей в файле POM. Если применимо, используйте Azure Spring Boot BOM.

Зависимости, перечисленные в Azure SDK BOM, тщательно проверяются, чтобы избежать конфликтов зависимостей.

Избегайте ненужных зависимостей

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

Обновление версий зависимостей

Если переключиться на последнюю Azure SDK BOM не помогает, определите библиотеки, вызывающие конфликты и используемые им компоненты. (Дополнительные сведения см. в разделе "Просмотр дерева зависимостей " ранее в этой статье.) Попробуйте обновить до более новой версии, которая защищает от уязвимостей системы безопасности и часто приносит новые функции, улучшения производительности и исправления ошибок.

Избегайте понижения Azure SDK версии, так как она может предоставлять приложению известные уязвимости и проблемы.

Библиотеки оттенков

Иногда нет сочетания библиотек, которые работают вместе, и затенение происходит как последний вариант.

Примечание.

Тенирование имеет значительные недостатки: оно увеличивает размер пакета и количество классов в classpath, затрудняет навигацию по коду и отладку, не перемещает код JNI, ломает рефлексию и может нарушать лицензии на код, среди прочего. Его следует использовать только после исчерпания других параметров.

Заливка позволяет включать зависимости в JAR во время сборки, а затем переименовывать пакеты и обновлять код приложения, чтобы использовать код в затенённом расположении. Конфликт зависимостей бриллиантов больше не является проблемой, так как существует две разные копии зависимости. Вы можете затенить библиотеку, которая имеет конфликтующую транзитивную зависимость или прямую зависимость приложения, как описано в следующем списке:

  • Транситивный конфликт зависимостей: например, для сторонней библиотеки A требуется Джексон 2.9, который Azure SDKs не поддерживается, и обновление A невозможно. Создайте новый модуль, который включает в себя A и оттенки (перемещает) Джексон 2.9 и, при необходимости, другие зависимости A.
  • Конфликт зависимостей приложения: приложение использует Джексон 2.9 напрямую. Хотя вы работаете над обновлением кода, вы можете оттенить и переместить Джексон 2.9 в новый модуль с перемещенными классами Джексона.

Примечание.

Создание толстых JAR-архивов с перемещенными классами Jackson не устраняет конфликт версии в этих примерах - это только приводит к использованию одной затененной версии Jackson.

Создайте толстый JAR-файл

Такие среды, как Databricks или Apache Spark, имеют настраиваемое управление зависимостями и предоставляют общие библиотеки, такие как Джексон. Чтобы избежать конфликта с предоставленными библиотеками, может потребоваться создать толстый JAR-файл, содержащий все зависимости. Для получения дополнительной информации см. Apache Maven Shade Plugin. Во многих случаях перенос классов Джексона (com.fasterxml.jackson) устраняет проблему. Иногда такие среды также предоставляют свою версию Azure SDK, поэтому вас может вынудить переместить пространство имен com.azure, чтобы обойти конфликты версий.

Общие сведения о совместимых версиях зависимостей

Сведения о зависимостях, связанных с azure-core, и их версиях см. в azure-core в центральном репозитории Maven Central. В следующей таблице приведены некоторые общие рекомендации.

Зависимость Поддерживаемые версии
Джэксон 2.10.0 и более новые дополнительные версии совместимы. Дополнительные сведения см. в разделе "Поддержка нескольких версий Джексона ".
SLF4J 1.7.*
netty-tcnative-boringssl-static 2.0.*
нетти-общий 4.1.*
ядро реактора 3.X.* — номера основных и дополнительных версий должны точно соответствовать тем, от которых зависит ваша azure-core версия. Дополнительные сведения см. в политике Project Reactor по нерекомендуемым причинам.

Поддержка нескольких версий библиотеки Jackson

Azure SDK для Java поддерживает работу с рядом версий Jackson. Самая низкая поддерживаемая версия — Джексон 2.10.0. Библиотеки клиентских приложений Azure SDK для Java настраивают свои конфигурации и использование Jackson в зависимости от версии, определенной во время выполнения программы. Эта корректировка обеспечивает более высокую совместимость со старыми версиями платформы Spring, Apache Spark и другими общими средами. Приложения могут понижать версии Джексона до 2.10.0 или выше без нарушения совместимости с клиентскими библиотеками Azure SDK для Java.

Примечание.

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

При установке определенной версии Jackson, обязательно выполните это для всех модулей, используемых Azure SDK, которые показаны в следующем списке:

  • jackson-annotations
  • jackson-core
  • jackson-databind
  • jackson-dataformat-xml
  • jackson-datatype-jsr310

Миграция из Джексона в azure-json

Azure клиентские библиотеки для Java находятся в процессе миграции на azure-json, которая не зависит от сторонних компонентов и предлагает общие примитивы, абстракции и вспомогательные средства для JSON.

Такие среды, как Apache Spark, Apache Flink и Databricks, могут содержать более старые версии azure-core, которые еще не зависят от azure-json. В результате при использовании более новых версий библиотек Azure в таких средах могут возникать ошибки, аналогичные java.lang.NoClassDefFoundError: com/azure/json/JsonSerializable. Можно смягчить эту ошибку, добавив явную зависимость от azure-json.

Дальнейшие действия

Теперь, когда вы знакомы с конфликтами версий зависимостей и способами их устранения, ознакомьтесь с соответствующей информацией в Dependency Management для Java, чтобы узнать о лучших способах их предотвращения.