Ich stieß heute auf einen sehr unerwarteten Fehler und während ich in der Lage war, das Problem als Ganzes zu beheben, bin ich mir nicht ganz sicher, warum es was tat es tat es.ConcurrentHashMap Absturz-Anwendung kompiliert mit JDK 8 aber Targeting JRE 7
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 eine ConcurrentHashMap
und musste über die Schlüssel in der Map iterieren. Dazu habe ich die map.keySet()
verwendet, die laut 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 Recherchen fand ich heraus, dass Java8-Implementierung für ConcurrentHashMap
die .keySet()
-Methode eine KeySetView<K,V>
zurückgibt.
Ich habe das Problem behoben, indem ich von map.keySet()
auf Enumeration<K>
mit map.keys()
umgestellt habe.
Jetzt ist meine Vermutung, das Problem ist, dass, obwohl das Projekt kompiliert Targeting Java7 seit dem JDK8 verwendet wurde die Java8-Bibliotheken enthalten waren, aber warum hat es nicht einen Fehler oder eine Ausnahme geworfen, wenn es das Mismatch getroffen?
Wie gefragt ist hier ein Code-Schnipsel:
class MapProcessing
{
private ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<String, Object>();
public MapProcessing()
{
map.put("First",new Object());
map.put("Second",new Object());
map.put("Third",new Object());
}
public void processing()
{
// when calling this type of loop causes a freeze on our system.
for(String key : map.keySet())
{
System.out.println(key);
}
}
public void working()
{
// This is what I had to do to fix the problem.
Enumeration<String> keys = map.keys();
while(keys.hasMoreElements())
{
String key = keys.nextElement();
System.out.println(key);
}
}
}
Wir kompilieren verwenden Oracle JDK 8 build 40 ein Ziel für 1,7 und 1,7 Quelle im javac auf einem Windows 2012 Server.
Der Code wird mit Oracle JVM 7 Build 25 unter Windows 2012-Server ausgeführt.
Haben Sie versucht, es nach dem Anschließen JDK 8 zu reinigen? –
@suresh die Build-Umgebung ist ein Jenkins. Als wir zu JDK8 wechselten, löschten wir den Arbeitsbereich und führten dann einen neuen Build durch. Dies würde bedeuten, dass der Code frisch aus SVN ausgecheckt und dann erstellt wurde. Ich bin mir nicht sicher, was Sie meinen, indem Sie es anders als den Standardaufruf zu einem "sauberen" Ziel in der Ameise reinigen, die geschieht. – JRSofty
können Sie ein Code-Snippet und die genaue JVM-Version und Hersteller + OS? KeySetView implementiert Set , so dass dies zumindest kein Problem sein sollte –
salyh