Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel werden Abhängigkeitsversionskonflikte und deren Problembehandlung beschrieben.
Azure-Clientbibliotheken für Java sind von beliebten Drittanbieterbibliotheken wie den folgenden abhängig:
Viele Java-Anwendungen und Frameworks verwenden diese Bibliotheken direkt oder transitiv, was zu Versionskonflikten führt. Abhängigkeitsmanager wie Maven und Gradle lösen alle Abhängigkeiten auf, sodass nur eine einzelne Version jeder Abhängigkeit vom Klassenpfad vorhanden ist. Es ist jedoch nicht garantiert, dass die aufgelöste Abhängigkeitsversion mit allen Verbrauchern dieser Abhängigkeit in Ihrer Anwendung kompatibel ist. Weitere Informationen finden Sie in der Einführung in den Abhängigkeitsmechanismus aus der Maven-Dokumentation sowie unter Grundlegendes zur Abhängigkeitsauflösung aus der Gradle-Dokumentation.
Die API-Inkompatibilität von direkten Abhängigkeiten führt zu Kompilierungsfehlern. Inkompatibilitäten aufgrund von Diamantabhängigkeiten (Diamond dependency) führen in der Regel zu Laufzeitfehlern wie NoClassDefFoundError, NoSuchMethodError, oder zu LinkageError. Nicht alle Bibliotheken halten sich streng an die semantische Versionierung, und Breaking Changes werden manchmal innerhalb der gleichen Hauptversion eingeführt.
Diagnostizieren von Problemen im Zusammenhang mit Versionskonflikten
In den folgenden Abschnitten werden Methoden zum Diagnostizieren von Problemen mit versionskonflikten beschrieben.
Verwenden des Azure SDK für Java-Buildtools
Das Azure SDK für Java-Buildtool, das in "Erste Schritte mit Azure SDK" und Apache Maven eingeführt wurde, hilft bei der Identifizierung häufig auftretender Probleme. Es wird empfohlen, dieses Buildtool zu Ihrem Projekt hinzuzufügen und auszuführen, indem Sie das azure:run Maven-Ziel zu Ihrem regulären Buildprozess hinzufügen. Mit der entsprechenden Konfiguration können Sie Abhängigkeitskonflikte proaktiver identifizieren und lösen, bevor sie zur Laufzeit zu Problemen werden.
Anzeigen einer Abhängigkeitsstruktur
Führen Sie mvn dependency:tree oder gradle dependencies --scan aus, um die vollständige Abhängigkeitsstruktur für Ihre Anwendung anzuzeigen – einschließlich Versionsnummern.
mvn dependency:tree -Dverbose enthält weitere Informationen, kann aber irreführend sein. Weitere Informationen finden Sie in der Maven-Dokumentation unter Apache Maven Dependency Tree . Sehen Sie sich für jede Bibliothek, bei der Sie einen Versionskonflikt vermuten, die Versionsnummer an, und ermitteln Sie, welche Komponenten davon abhängen.
Die Abhängigkeitsauflösung in Entwicklungs- und Produktionsumgebungen kann unterschiedlich funktionieren. Apache Spark, Apache Flink, Databricks und IDE-Plug-Ins benötigen zusätzliche Konfiguration für benutzerdefinierte Abhängigkeiten. Sie können auch eigene Versionen von Azure-Clientbibliotheken oder gängigen Komponenten mitbringen. Weitere Informationen finden Sie in den folgenden Artikeln:
- Bündeln der Abhängigkeiten Ihrer Anwendung für Apache Spark
- Projektkonfiguration für Apache Flink
- So aktualisieren Sie eine Maven-Bibliothek in Databricks für Databricks ordnungsgemäß
Weitere Informationen zur Konfliktlösung in solchen Umgebungen finden Sie im Abschnitt Erstellen einer fat-JAR-Datei weiter unten in diesem Artikel.
Konfigurieren von Azure-Funktionen
Die interne Abhängigkeitsversion von Azure Functions (nur mit Java 8) hat Vorrang vor einem vom Benutzer bereitgestellten. Diese Abhängigkeit verursacht Versionskonflikte, insbesondere mit Jackson, Netty und Reaktor.
Um dieses Problem zu beheben, legen Sie die FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBS Umgebungsvariable auf true oder 1. Achten Sie darauf, die Azure-Funktionstools (v2 oder v3) auf die neueste Version zu aktualisieren.
Hinweis
Diese Konfiguration gilt nur für Azure-Funktionen, die Java 8 ausführen. Funktionen, die Java 11 ausführen, benötigen keine spezielle Konfiguration.
Konfigurieren von Apache Spark
Das Azure SDK für Java unterstützt mehrere Versionen von Jackson. Manchmal können jedoch Probleme auftreten, die auf Ihre Buildtools und die Reihenfolge, in der die Abhängigkeitsauflösung durchgeführt wird, zurückzuführen sind. Ein gutes Beispiel für dieses Problem ist apache Spark, Version 3.0.0 und höher, die von Jackson 2.10 abhängt. Während es mit dem Azure SDK für Java kompatibel ist, entdecken Entwickler häufig, dass stattdessen eine neuere Version von Jackson verwendet wird, was zu Inkompatibilitäten führt. Um dieses Problem zu beheben, sollten Sie eine bestimmte Version von Jackson festlegen (eine, die mit Spark kompatibel ist). Weitere Informationen finden Sie im Abschnitt "Support für mehrere Jackson-Versionen " in diesem Artikel.
Wenn Sie frühere Versionen von Spark verwenden oder eine andere Bibliothek, die Sie verwenden, eine noch frühere Version von Jackson erfordert, die das Azure SDK für Java nicht unterstützt, lesen Sie diesen Artikel weiter, um mögliche Abhilfemaßnahmen zu finden.
Jackson-Laufzeitversion erkennen
In Azure Core 1.21.0 haben wir laufzeiterkennung und bessere Diagnose der Jackson-Laufzeitversion hinzugefügt.
Wenn Sie LinkageError (oder eine seiner Unterklassen) im Zusammenhang mit der Jackson-API sehen, überprüfen Sie die Meldung der Ausnahme auf Informationen zur Laufzeitversion. Beispiel: 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
Suchen Sie nach Warnungs- und Fehlerprotokollen von JacksonVersion. Weitere Informationen finden Sie unter Konfigurieren der Protokollierung im Azure SDK für Java. Beispiel: [main] ERROR com.azure.core.implementation.jackson.JacksonVersion - Version '2.9.0' of package 'jackson-core' is not supported (too old), please upgrade.
Hinweis
Überprüfen Sie, ob alle Jackson-Pakete dieselbe Version haben.
Eine Liste der Pakete, die vom Azure SDK und den unterstützten Jackson-Versionen verwendet werden, finden Sie im Abschnitt "Support für mehrere Jackson-Versionen ".
Verminderung von Versionskonfliktproblemen
In den folgenden Abschnitten wird beschrieben, wie Versionskonfliktprobleme behoben werden.
Azure SDK-BOM verwenden
Verwenden Sie die neueste stabile Azure SDK-BOM , und geben Sie keine Azure SDK- und Abhängigkeitsversionen in Ihrer POM-Datei an. Verwenden Sie ggf. die Azure Spring Boot BOM.
Die im Azure SDK-BOM aufgeführten Abhängigkeiten werden streng getestet, um Abhängigkeitskonflikte zu vermeiden.
Vermeiden sie unnötige Abhängigkeiten
Entfernen Sie Abhängigkeiten, falls möglich. Manchmal verfügt eine Anwendung über Abhängigkeiten von mehreren Bibliotheken, die im Wesentlichen dieselbe Funktionalität bereitstellen. Solche unnötigen Abhängigkeiten setzen Anwendungen Sicherheitsrisiken, Versionskonflikten sowie Support- und Wartungskosten aus.
Aktualisieren von Abhängigkeitsversionen
Wenn der Wechsel zur neuesten Azure SDK-BOM nicht hilfreich ist, identifizieren Sie die Bibliotheken, die Konflikte verursachen, und die Komponenten, die sie verwenden. (Weitere Informationen finden Sie im Abschnitt " Anzeigen einer Abhängigkeitsstruktur " weiter oben in diesem Artikel.) Versuchen Sie, auf eine neuere Version zu aktualisieren, die vor Sicherheitsrisiken schützt, und bietet häufig neue Features, Leistungsverbesserungen und Fehlerbehebungen.
Vermeiden Sie es, die Version des Azure SDK zu herabzustufen, da dies Ihre Anwendung möglicherweise bekannten Sicherheitsrisiken und Problemen aussetzen kann.
Verwenden von Shading für Bibliotheken
Manchmal gibt es keine Kombination von Bibliotheken, die zusammenarbeiten, und Schattierung kommt als letzte Möglichkeit.
Hinweis
Die Schattierung hat erhebliche Nachteile: Es erhöht die Paketgröße und die Anzahl der Klassen auf dem Klassenpfad, macht die Codenavigation und das Debuggen hart, verschiebt JNI-Code nicht, bricht Spiegelung und kann unter anderem Codelizenzen verletzen. Es sollte nur verwendet werden, nachdem andere Optionen erschöpft sind.
Mithilfe von Shading können Sie zur Erstellungszeit Abhängigkeiten innerhalb eines JAR einschließen, dann Pakete umbenennen und den Anwendungscode aktualisieren, um den Code im schattierten Paket zu verwenden. Der Diamond Dependency-Konflikt ist kein Problem mehr, da es zwei verschiedene Versionen einer Abhängigkeit gibt. Sie können eine Bibliothek schattieren, die eine widersprüchliche transitive Abhängigkeit oder eine direkte Anwendungsabhängigkeit aufweist, wie in der folgenden Liste beschrieben:
-
Transitive Abhängigkeitskonflikt: Beispielsweise erfordert die Drittanbieterbibliothek
Adie Verwendung von Jackson 2.9, die von den Azure-SDKs nicht unterstützt wird, und es ist nicht möglich,Azu aktualisieren. Erstellen Sie ein neues Modul, dasAenthält und Jackson 2.9 (sowie optional weitere Abhängigkeiten vonA) mittels Shading verlagert. - Anwendungsabhängigkeitskonflikt: Ihre Anwendung verwendet Jackson 2.9 direkt. Im Zuge der Aktualisierung Ihres Codes können Sie Jackson 2.9 stattdessen mittels Shading in ein neues Modul mit verlagerten Jackson-Klassen verlagern.
Hinweis
Durch die Erstellung einer fat-JAR-Datei mit verlagerten Jackson-Klassen wird in diesen Beispielen kein Versionskonflikt gelöst, sondern nur eine einzelne Shading-Version von Jackson erzwungen.
Erstellen einer fat-JAR-Datei
Umgebungen wie Databricks oder Apache Spark verfügen über benutzerdefinierte Abhängigkeitsverwaltung und bieten allgemeine Bibliotheken wie Jackson. Um Konflikte mit bereitgestellten Bibliotheken zu vermeiden, sollten Sie einen fetten JAR erstellen, der alle Abhängigkeiten enthält. Weitere Informationen finden Sie unter Apache Maven Shade Plugin. In vielen Fällen mildert die Verlagerung von Jackson-Klassen (com.fasterxml.jackson) das Problem. Manchmal bringen solche Umgebungen auch ihre eigene Version von Azure-SDKs mit, sodass Sie möglicherweise gezwungen werden, den Namespace zu verschieben com.azure , um Versionskonflikte zu umgehen.
Verständnis von kompatiblen Abhängigkeitsversionen
Informationen zu azure-corespezifischen Abhängigkeiten und deren Versionen finden Sie unter azure-core im Maven Central Repository. Die folgende Tabelle enthält einige allgemeine Überlegungen:
| Abhängigkeit | Unterstützte Versionen |
|---|---|
| Jackson | 2.10.0 und neuere Nebenversionen sind kompatibel. Weitere Informationen finden Sie im Abschnitt "Support für mehrere Jackson-Versionen ". |
| SLF4J | 1.7.* |
| netty-tcnative-boringssl-static | 2.0.* |
| Netty-allgemein | 4.1.* |
| Reaktorkern | 3.X.* – Haupt- und Nebenversionsnummern müssen genau mit denen übereinstimmen, von denen Ihre azure-core Version abhängt. Weitere Informationen finden Sie in der Veraltungsrichtlinie von Project Reactor. |
Unterstützung für mehrere Jackson-Versionen
Das Azure SDK für Java unterstützt das Arbeiten mit einer Reihe von Jackson-Versionen. Die niedrigste unterstützte Version ist Jackson 2.10.0. Das Azure SDK für Java-Clientbibliotheken passen ihre Konfiguration und die Jackson-Verwendung abhängig von der Version an, die zur Laufzeit erkannt wird. Diese Anpassung ermöglicht eine höhere Kompatibilität mit älteren Versionen des Spring-Frameworks, Apache Spark und anderen gängigen Umgebungen. Anwendungen können Jackson-Versionen (auf 2.10.0 oder höher) herunterstufen, ohne das Azure SDK für Java-Clientbibliotheken zu unterbrechen.
Hinweis
Die Verwendung alter Versionen von Jackson kann Anwendungen bekannten Sicherheitsrisiken und Problemen aussetzen. Weitere Informationen finden Sie in der Liste der bekannten Sicherheitsrisiken für Jackson-Bibliotheken.
Stellen Sie beim Anheften einer bestimmten Version von Jackson sicher, dass Sie dies für alle Module des Azure SDK tun, die in der folgenden Liste angezeigt werden:
jackson-annotationsjackson-corejackson-databindjackson-dataformat-xmljackson-datatype-jsr310
Migration von Jackson zu azure-json
Azure-Clientbibliotheken für Java befinden sich im Prozess der Migration zu Azure-JSON, die nicht von Drittanbieterkomponenten abhängig ist und freigegebene Grundtypen, Abstraktionen und Hilfsprogramme für JSON bietet.
Umgebungen wie Apache Spark, Apache Flink und Databricks könnten ältere Versionen von azure-core bereitstellen, die noch nicht von azure-json abhängig sind. Wenn Sie daher neuere Versionen von Azure-Bibliotheken in solchen Umgebungen verwenden, erhalten Sie möglicherweise Ähnliche Fehler java.lang.NoClassDefFoundError: com/azure/json/JsonSerializable. Sie können diesen Fehler beheben, indem Sie eine explizite Abhängigkeit auf azure-json hinzufügen.
Nächste Schritte
Nachdem Sie mit Abhängigkeitsversionskonflikten und deren Problembehandlung vertraut sind, finden Sie unter "Abhängigkeitsverwaltung für Java " Informationen zu den besten Methoden, um sie zu verhindern.