ConcurrentHashMap Absturz-Anwendung kompiliert mit JDK 8 aber Targeting JRE 7

8

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.

    
JRSofty 05.10.2015, 17:06
quelle

2 Antworten

12

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%     
salyh 05.10.2015, 18:47
quelle
2

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.

    
Powerlord 05.10.2015 18:15
quelle