Ho avuto un errore molto inaspettato oggi e mentre sono riuscito a trovare un modo per risolvere il problema nel suo complesso non sono sicuro di capire completamente perché ha fatto cosa lo ha fatto.Applicazione Crash ConcurrentHashMap compilata con JDK 8 ma con targeting JRE 7
Il codice con cui sto lavorando è stato originariamente scritto con un JDK 7 ambiente naturalmente mira JRE 7. Nel codice Io sto usando un ConcurrentHashMap
e necessari per scandire le chiavi nella mappa. Per questo stavo usando il map.keySet()
che secondo JavaDocs dovrebbe restituire un Set<K>
. Questo ha funzionato fino a quando il nostro ambiente di costruzione non è passato a JDK8.
Quando siamo passati a JDK8 mi sono assicurato che stavo chiamando un target/source per 1.7 quando si chiama il javac. Quindi sono rimasto piuttosto sorpreso quando il codice ha iniziato a non funzionare correttamente quando voleva scorrere le chiavi della mappa. Nessun errore è stato lanciato, nessuna eccezione, il thread semplicemente si è fermato. Dopo aver effettuato alcune ricerche, ho scoperto che l'implementazione di Java8 per ConcurrentHashMap
il metodo .keySet()
restituisce un valore KeySetView<K,V>
.
Ho risolto il problema passando dall'utilizzo di map.keySet()
a un Enumeration<K>
utilizzando map.keys()
.
Ora la mia ipotesi sul problema è che sebbene il progetto sia stato compilato per il targeting Java7 dal momento che il JDK8 è stato utilizzato, le librerie Java8 sono state incluse, ma perché non ha generato un errore o un'eccezione quando ha colpito la mancata corrispondenza?
come chiesto: ecco un frammento di codice:
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);
}
}
}
Stiamo compilando utilizzando Oracle JDK 8 Build 40 con un obiettivo per 1,7 e 1,7 fonte nel javac su un server Windows 2012.
Il codice è in esecuzione utilizzando Oracle JVM 7 build 25 in esecuzione sul server Windows 2012.
Hai provato a pulirlo dopo aver collegato JDK 8? –
@suresh l'ambiente di costruzione è un Jenkins. Quando ci siamo spostati su JDK8 abbiamo eliminato lo spazio di lavoro e poi eseguito una nuova build. Ciò significherebbe che il codice è stato appena estratto da SVN e quindi creato. Non sono sicuro di cosa intendi per pulirlo a parte la chiamata standard a un target "pulito" nella formica, cosa che succede. – JRSofty
puoi pubblicare uno snippet di codice e la versione esatta di JVM e il sistema operativo + OS? Strumenti KeySetView Impostare in modo che almeno questo non dovrebbe essere un problema reale –
salyh