2015-06-09 22 views
19

Ricevo un ArrayIndexOutOfBoundsException all'avvio del servizio (creazione bean) quando utilizzo le funzionalità di Java 8.ArrayOutOfBoundsException sulla creazione di bean durante l'utilizzo di costrutti Java 8

Java 8 è stato configurato e ha funzionato. Il codice viene compilato correttamente. All'avvio del servizio, il servizio non riesce ad ascoltare la porta man mano che i bean non vengono creati. Quando cambio il codice (rimuovi i costrutti java 8) il servizio si avvia e tutto funziona correttamente.

Questo è il codice che sto usando (il codice di lavoro per il quale avvia il servizio):

for (Item itemObject : response) { 
    if (itemObject.hasId()) { 
     idList.add(String.valueOf(itemObject.Id()); 
    } 
} 

Stesso codice utilizzando Java 8 costrutti:

response.parallelStream() 
     .filter(itemObject -> itemObject.hasId()) 
     .map(itemObject -> itemObject.getId()) 
     .forEach(id -> idList.add(id)); 

Il fagiolo per la classe che contiene questo pezzo di codice viene creato utilizzando la scansione dei componenti.

Quello che segue è il messaggio di eccezione quando il secondo blocco di codice viene utilizzato al posto del primo:

Exiting with throwable: java.lang.IllegalArgumentException: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: URL [jar:file:/workspace/.../GetContainerIdForFcSkuAdapter.class]; nested exception is java.lang.ArrayIndexOutOfBoundsException: 51880 
java.lang.IllegalArgumentException: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: URL [jar:file:/workspace....Some.class]; nested exception is java.lang.ArrayIndexOutOfBoundsException: 51880 

Che non ha senso per me è, perché è il codice all'interno di una funzione (che è non il costruttore della classe bean) durante la creazione del bean. Lo chiedo, perché l'eccezione non c'è quando utilizzo il ciclo for normale invece del flusso parallelo. Non dovrebbe sorgere un ArrayOutOfBoundsException quando viene chiamata la funzione e questo codice viene effettivamente utilizzato.

Come posso risolvere questo problema?

+2

Che cos'è 'idList'? Nella seconda versione stai usando 'parallelStream', quindi aggiungi elementi a questo elenco da più thread. L'implementazione della lista che usi thread-safe? L'errore scompare se usi 'stream()' invece di 'parallelStream()'? – Jesper

+2

Inoltre, il modo normale per ottenere il contenuto di un flusso in un elenco è 'Elenco list = stream.collect (Collectors.toList())' invece di 'stream.forEach (o -> list.add (o)' – Jesper

+0

non sto aggiungendo realmente da più thread, Java sta srotolando internamente il ciclo e parallelizzando, esiste ancora un errore sull'utilizzo del vapore, come detto, il blocco del codice deve essere eseguito quando viene chiamata la funzione, non sulla creazione di bean. questo blocco si usa e dà ArrayIndexOutOfBounds all'avvio del servizio. Per favore guarda la mia risposta qui sotto e dimmi se pensi che potrebbe essere un motivo – akshitBhatia

risposta

34

Quale versione di Spring usi? È necessario eseguire l'aggiornamento a Spring 4 per utilizzare le espressioni lambda Java 8.

+1

Sì, 4.0.X.RELEASE funziona con java 8. – Buminda

8

Ho trovato un bug di recente quando si utilizza Spring 3.0.5, che sembra essere risolto in 4.0.5. Ecco i dettagli.

Se si dispone di una classe che ha un costruttore con parametri e ha anche un metodo che utilizza un'espressione lambda (introdotta in Java 8), si verifica un'eccezione ArrayIndexOutOfException durante la creazione di un bean per quella classe.

+2

Questo non è proprio un bug. Spring 3 non supporta completamente Java 8, quindi usare Lambdas con Spring 3.0.5 è un errore utente e non un bug di Spring. –

+2

Ho appena incontrato è e sembrava terribilmente strano. È successo come dici tu, quando ho aggiunto un parametro al costruttore del bean. Stavo usando for every in un paio di posti. Non penso che avrei mai fatto questa connessione che un forEach in qualsiasi parte della classe avrebbe rotto la sua istanza di bean con un'eccezione di limiti di array. Oh bene - grazie, Stack Overflow! – botimer

+2

mi hai liberato da un mal di testa da incubo! Grazie ! – Guillaume