NoSuchMethodError: java.util.concurrent.ConcurrentHashMap.keySet()

Eingetragen bei: Java | 0

Nachdem ich auf meinem Entwicklungsrechner auf Java 8 aktualisiert habe, bin ich auf ein zuerst merkwürdig erscheinendes Problem gestoßen. Obwohl ich Java 8 installiert habe kompiliere ich in Eclipse für Java 7, da auf dem Anwendungsserver (noch) Java 7 verwendet wird.

Beim Testen auf dem Staging System (ebenfalls mit Java 7) trat folgende Exception auf:

Exception in thread „main“ java.lang.NoSuchMethodError: java.util.concurrent.ConcurrentHashMap.keySet()Ljava/util/concurrent/ConcurrentHashMap$KeySetView;

Zuerst konnte ich den Fehler lokal nicht reproduzieren und die Fehlermeldung machte auch keinen Sinn. Warum sollte die Methode keySet() nicht existieren? Zumal ich an der Klasse, in der ich die ConcurrentHashMap verwende, nichts geändert hatte. Es gab bisher ja auch keine Probleme und beim Kompilieren wurden keine Fehler geworfen. Das einzige was sich geändert hatte war das Update von Java 7 auf Java 8.

Und natürlich ergibt das ganze Sinn, wenn man sich die Sache genauer ansieht.

Von Java 7 zu Java 8 wurde die keySet() Methode geändert. In Java 7 liefert keySet() ein Set<K> zurück. In Java 8 dagegen wird ConcurrentHashMap.KeySetView<K,V> zurück gegeben. Beim Kompilieren mit Java 8 wird (auch wenn wir für Java 7 kompatibel kompilieren), als Rückgabewert die KeySetView erwartet. Wenn wir nun die Klasse mit Java 7 ausführen wird die Methode, die ein KeySetView zurück gibt nicht gefunden und es kommt zum NoSuchMethodError.

Ein Beispiel

Eine Kleine Testklasse demonstriert das Ganze:

Wenn wir die Klasse mit Java 8 und Ziel Java 7 kompilieren, wird eine Warnung ausgegeben.

Wenn man die Klasse nun mit Java 8 ausführt ist alles in Ordnung.

Wenn wir aber die Klasse mit Java 7 ausführen, bekommen wir den bekannten Fehler:

 Und wie können wir das Problem lösen?

Die erste Lösungsmöglichkeit ist offensichtlich. Wir kompilieren einfach mit Java 7. Falls das nicht geht oder nicht gewünscht ist kann man auch aus Java 7 die rt.jar im bootclasspath angeben:

Beim Kompilieren kommt nun keine Warnung und beim Ausführen mit Java 7 auch kein Fehler mehr.

Die letzte Möglichkeit ist dann noch den Quelltext anzupassen. Statt

schreibt man:

 

Hinterlasse einen Kommentar