次の方法で共有


依存関係バージョンの競合のトラブルシューティング

この記事では、依存関係バージョンの競合とそのトラブルシューティング方法について説明します。

Java用Azureクライアント ライブラリは、次のような一般的なサード パーティ製ライブラリに依存します。

  • ジャクソン
  • Netty
  • 原子炉
  • SLF4J

多くのJavaアプリケーションやフレームワークでは、これらのライブラリが直接または推移的に使用されるため、バージョンの競合が発生します。 Maven や Gradle などの依存関係マネージャーは、すべての依存関係を解決して、クラスパスに対する各依存関係のバージョンが 1 つだけになるようにします。 ただし、解決された依存関係バージョンが、アプリケーション内のその依存関係のすべてのコンシューマーと互換性があるとは限りません。 詳細については、Maven ドキュメント の依存関係メカニズムの概要 と Gradle ドキュメントの 依存関係解決 についてを参照してください。

直接依存関係の API の非互換性により、コンパイル エラーが発生します。 通常、ダイヤモンドの依存関係 の非互換性により、 NoClassDefFoundError、 NoSuchMethodError、その他 のリンケージ エラーなどの実行時エラーが発生します。 すべてのライブラリが セマンティック バージョン管理に厳密に従っているわけではありません。また、破壊的変更が同じメジャー バージョン内で発生する場合があります。

バージョンの不一致の問題を診断する

以降のセクションでは、バージョンの不一致の問題を診断する方法について説明します。

Java 向けの Azure SDK ビルド ツールを使用する

Get started with Azure SDK and Apache Maven は、一般的に発生する問題を特定するのに役立ちます。 このビルド ツールをプロジェクトに追加し、通常のビルド プロセスに Maven ターゲットを追加して実行することをお勧めします。 適切な構成を使用すると、実行時に問題になる前に、依存関係の競合をより積極的に特定して解決できます。

依存関係ツリーを表示する

またはを実行して、アプリケーションの完全な依存関係ツリーとバージョン番号を表示します。 は、より多くの情報を提供しますが、誤解を招く可能性があります。 詳細については、Maven ドキュメントの Apache Maven 依存関係ツリー を参照してください。 バージョンの競合が疑われるライブラリごとに、そのバージョン番号を書き留めて、どのコンポーネントがそれに依存するかを判断します。

開発環境と運用環境での依存関係の解決は、動作が異なる場合があります。 Apache Spark、 Apache Flink、 Databricks、IDE プラグインには、カスタム依存関係用の追加の構成が必要です。 また、独自のバージョンの Azure クライアント ライブラリまたは共通コンポーネントを使用することもできます。 詳細については、次の記事を参照してください。

  • Apache Spark 用アプリケーションの依存関係のバンドル
  • Apache Flink のプロジェクト構成
  • Databricks for Databricks で Maven ライブラリを正しく更新する方法

このような環境での競合解決の詳細については、この記事で後述する 「Fat JAR の作成 」セクションを参照してください。

Azure Functionsの構成

Azure Functionsの内部依存関係バージョン (Java 8 のみ実行) は、ユーザーが指定したバージョンよりも優先されます。 この依存関係により、バージョンの競合 (特に Jackson、Netty、Reactor) が発生します。

この問題を解決するには、 環境変数を または に設定します。 Azure関数ツール (v2 または v3) を最新バージョンに更新してください。

この構成は、Java 8 を実行しているAzure Functionsにのみ適用されます。Java 11 を実行する関数には特別な構成は必要ありません。

Apache Spark を構成する

JavaのAzure SDKは複数のバージョンの Jackson をサポートしていますが、ビルド ツールとその依存関係解決の順序によっては問題が発生する場合があります。 この問題の良い例は、Apache Spark バージョン 3.0.0 以降であり、Jackson 2.10 に依存しています。 JavaのAzure SDKと互換性がありますが、開発者は多くの場合、より新しいバージョンの Jackson が代わりに使用されていることに気が付き、その結果非互換性が生じます。 この問題を軽減するには、特定のバージョンの Jackson (Spark と互換性のあるバージョン) をピン留めする必要があります。 詳細については、この記事の 「複数の Jackson バージョンのサポート 」セクションを参照してください。

以前のバージョンの Spark を使用している場合、または使用する別のライブラリで、JavaのAzure SDKでサポートされていない以前のバージョンの Jackson が必要な場合は、この記事を引き続き読んで軽減手順を確認してください。

Jackson ランタイム バージョンの検出

Azure Core 1.21.0 では、Jackson ランタイム バージョンのランタイム検出と診断の改善が追加されました。

Jackson API に関連する (またはそのサブクラスのいずれか) が表示される場合は、例外のメッセージでランタイム バージョン情報を確認してください。 例:

から警告ログとエラー ログを探します。 詳細については、Azure SDK for Java におけるログ記録の設定を参照してください。 例:

すべての Jackson パッケージのバージョンが同じであることを確認します。

Azure SDKおよびサポートされている Jackson バージョンで使用されるパッケージの一覧については、「Support for multiple Jackson versions」セクションを参照してください。

バージョンの不一致の問題を軽減する

以降のセクションでは、バージョンの不一致の問題を軽減する方法について説明します。

AZURE SDK BOM を使用する

最新の安定した Azure SDK BOM を使用し、POM ファイルにAzure SDKと依存関係のバージョンを指定しないでください。 該当する場合は、Azure Spring Boot BOM を使用します。

Azure SDK BOM に記載されている依存関係は、依存関係の競合を回避するために厳密にテストされます。

不要な依存関係を回避する

可能であれば、依存関係を削除します。 アプリケーションが、基本的に同じ機能を提供する複数のライブラリに依存している場合があります。 このような不要な依存関係により、アプリケーションはセキュリティの脆弱性、バージョンの競合、サポートとメンテナンスのコストにさらされます。

依存関係のバージョンを更新する

最新のAzure SDK BOM に切り替えても問題が解決しない場合は、競合の原因となっているライブラリと、それらを使用するコンポーネントを特定します。 (詳細については、この記事の前の「 依存関係ツリーの表示 」セクションを参照してください)。セキュリティの脆弱性から保護し、多くの場合、新機能、パフォーマンスの向上、バグ修正を行う新しいバージョンに更新してみてください。

アプリケーションが既知の脆弱性や問題にさらされる可能性があるため、Azure SDKバージョンのダウングレードは避けてください。

ライブラリのシェーディング

一緒に動作するライブラリの組み合わせが見つからない場合、最後の手段としてシャーディングを行うことがあります。

シェーディングには大きな欠点があります。これにより、クラスパスのパッケージ サイズとクラスの数が増え、コードのナビゲーションとデバッグが困難になり、JNI コードが再配置され、リフレクションが中断され、特にコード ライセンスに違反する可能性があります。 他のオプションが使い果たされた後にのみ使用する必要があります。

シェーディングを使用すると、ビルド時に JAR 内に依存関係を含め、パッケージの名前を変更し、網掛けされた場所でコードを使用するようにアプリケーション コードを更新できます。 依存関係には 2 つの異なるコピーがあるため、ひし形の依存関係の競合は問題ではなくなりました。 次の一覧で説明するように、競合する推移的な依存関係または直接のアプリケーションの依存関係を持つライブラリを網掛けすることができます。

  • 推移的依存関係の競合: たとえば、あるサードパーティのライブラリAでは、Azure SDKs がサポートしていない Jackson 2.9 が必要であり、Azure SDKs を更新することはできません。 と、Jackson 2.9をシャーディング(再配置)し、必要に応じてのその他の依存関係を含む新しいモジュールを作成します。
  • アプリケーションの依存関係の競合: アプリケーションは Jackson 2.9 を直接使用します。 コードの更新に取り組んでいる間に、Jackson 2.9 をシェーディングして新しいモジュールに再配置し、代わりに Jackson クラスを再配置することができます。

再配置された Jackson クラスを使用して Fat JAR を作成しても、これらの例ではバージョンの競合は解決されません。ジャクソンの単一のシェーディング バージョンのみが強制されます。

「ファット JAR(全ての依存関係を含む大きな JAR ファイル)を作成する」

Databricks や Apache Spark などの環境には、カスタム依存関係管理があり、Jackson などの一般的なライブラリが用意されています。 提供されているライブラリとの競合を回避するために、すべての依存関係を含む fat JAR を構築することをお勧めします。 詳細については、「 Apache Maven Shade Plugin」を参照してください。 多くの場合、Jackson クラス () を再配置すると、問題が軽減されます。 このような環境では独自のバージョンのAzure SDKsも使用される場合があるため、バージョンの競合を回避するために、com.azure 名前空間の再配置を強制される場合があります。

互換性のある依存関係のバージョンについて

固有の依存関係とそのバージョンについては、Maven Central リポジトリの azure-core を参照してください。 次の表は、一般的な考慮事項を示しています。

依存関係 サポートされているバージョン
ジャクソン 2.10.0 以降のマイナー バージョンには互換性があります。 詳細については、「 複数の Jackson バージョンのサポート 」セクションを参照してください。
SLF4J 1.7.*
netty-tcnative-boringssl-static 2.0.*
netty-common 4.1.*
炉心 3.X.* - メジャー バージョン番号とマイナー バージョン番号は、 バージョンが依存する番号と完全に一致している必要があります。 詳細については、廃止に関する Project Reactor ポリシーを参照してください。

複数の Jackson バージョンのサポート

JavaのAzure SDKでは、さまざまな Jackson バージョンの操作がサポートされています。 サポートされている最小バージョンは Jackson 2.10.0 です。 Javaクライアント ライブラリのAzure SDKは、実行時に検出されるバージョンに応じて、構成と Jackson の使用を調整します。 この調整により、古いバージョンの Spring Framework、Apache Spark、およびその他の一般的な環境との互換性が向上します。 アプリケーションは、Javaクライアント ライブラリのAzure SDKを中断することなく、Jackson のバージョンを (2.10.0 以降に) ダウングレードできます。

以前のバージョンの Jackson を使用すると、アプリケーションが既知の脆弱性や問題にさらされる可能性があります。 詳細については、 Jackson ライブラリの既知の脆弱性の一覧を参照してください。

特定のバージョンの Jackson をピン留めする場合は、次の一覧に示すように、Azure SDKで使用されるすべてのモジュールに対して行ってください。

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

Jackson から azure-json への移行

Java用Azureクライアント ライブラリは、サード パーティのコンポーネントに依存しない azure-json への移行中であり、JSON の共有プリミティブ、抽象化、ヘルパーを提供します。

Apache Spark、Apache Flink、Databricks などの環境では、にまだ依存していない古いバージョンのが提供される場合があります。 その結果、このような環境で新しいバージョンのAzure ライブラリを使用すると、java.lang.NoClassDefFoundError: com/azure/json/JsonSerializable のようなエラーが発生する可能性があります。 このエラーを軽減するには、 に明示的な依存関係を追加します。

次のステップ

依存関係のバージョン競合とそのトラブルシューティング方法について理解したら、Javaの依存関係管理を参照して、それらを防ぐための最善の方法についての情報をご覧ください。