Ich bin heute auf einen sehr unerwarteten Fehler gestoßen und während ich in der Lage war, einen Weg zu finden, das Problem als Ganzes zu lösen, bin ich mir nicht sicher, ob ich vollständig verstehe, warum es das getan hat.
Der Code, mit dem ich arbeite, wurde ursprünglich mit einer JDK 7-Umgebung geschrieben, die natürlich auf JRE 7 abzielte. Im Code verwendete ich ConcurrentHashMap
und musste über die Schlüssel in der Map iterieren. Dazu habe ich die map.keySet()
verwendet, die laut den JavaDocs eine Set<K>
zurückgeben soll. Dies funktionierte gut, bis unsere Build-Umgebung zu JDK8 wechselte.
Als wir zu JDK8 wechselten, stellte ich sicher, dass ich beim Aufruf des Javacs ein Ziel / eine Quelle für 1.7 anrief. So war ich ziemlich überrascht, als der Code zu versagen begann, als er die Schlüssel der Karte durchlaufen wollte. Es wurde kein Fehler ausgelöst, keine Ausnahme, der Thread wurde einfach gestoppt. Nach einigen Nachforschungen fand ich heraus, dass Java8's Implementierung für ConcurrentHashMap
die .keySet()
Methode ein KeySetView<K,V>
zurückgibt.
Ich habe das Problem behoben, indem ich von map.keySet()
auf Enumeration<K>
mit map.keys()
umgestellt habe.
Nun, ich schätze das Problem ist, dass, obwohl das Projekt auf Java7 kompiliert wurde, seit das JDK8 verwendet wurde, die Java8 Bibliotheken enthalten waren, aber wieso hat es keinen Fehler oder eine Ausnahme geworfen, als es das Mismatch getroffen hat? p>
Wie hier gefragt, ist ein Code-Snippet:
%Vor%Wir kompilieren mit Oracle JDK 8 Build 40 unter Verwendung eines Ziels für 1.7 und Quelle 1.7 im javac auf einem Windows 2012 Server.
Der Code wird mit Oracle JVM 7 Build 25 auf dem Windows 2012-Server ausgeführt.
Wenn ich Ihren Code mit Java 8 und javac -source 1.7 -target 1.8 kompiliere und dann mit Java 7 laufe, bekomme ich ein
%Vor%Dies liegt daran, dass der Byte-Code wie
aussieht %Vor%und explizit auf ConcurrentHashMap $ KeySetView verweisen, die in Java 7 nicht vorhanden ist. Ich bin auf Mac mit Java 1.7.0_79 und 1.8.0_45
Wenn Sie den Code in (nur die Kartenschnittstelle verwenden) ändern:
%Vor%Dann funktioniert es für mich. Bytecode sieht dann wie
aus %Vor% Wenn Sie ein Projekt mit einem neueren JDK mit dem Argument -source
für eine ältere Version erstellen, erhalten Sie diese Compiler-Warnung:
warning: [options] bootstrap class path not set in conjunction with -source 1.7
In diesem Blogeintrag wird erläutert, was es bedeutet.
Im Grunde erhalten Sie diese Warnung, weil Java sie mit älteren Sprachregeln kompiliert, aber gegen die neuere Klassenbibliothek ... und es gibt einige Kompatibilitätsprobleme mit den Java 8-Versionen, da Oracle einige der internen Klassen verschoben hat. p>
Das Problem besteht darin, das Argument -bootclasspath
zu verwenden, um es beim Kompilieren auf die rt.jar
der älteren Version zu richten.
Tags und Links java iteration concurrenthashmap