2015-05-11 10 views
8

Ho visto di recente uno strano comportamento nella mia applicazione che non posso davvero spiegare. Si verificano in modo non frequente, quindi non posso riprodurli. Mentre il luogo in cui si verificano questi problemi cambia, la parte comune sembra essere che un array cambia dimensione dopo che è stato creato (lo so, questo non è possibile, quindi: comportamento strano).variazioni della lunghezza dell'array in openjdk

Un paio di esempi per rendere il mio punto chiaro:

java.lang.StringIndexOutOfBoundsException: String index out of range: 86 
    at java.lang.String.checkBounds(String.java:409) 
    at java.lang.String.<init>(String.java:577) 
    at com.acunia.fleet.diagnostics.providers.tacho.VDOKLineInputParser.getRealDriverID(Unknown Source) 

Il codice che potrebbe causare questo:

public String getRealDriverID(byte[] buffer) { 
    if (buffer.length > 86 && isDriverCardInserted(buffer)) { 
    return new String(buffer, 70, 16); 
    } 
    return null; 
} 

Quindi per prima cosa verificare che il buffer è abbastanza grande (più di 86 byte) prima di provare a creare una stringa da loro.

Un secondo esempio:

java.lang.ArrayIndexOutOfBoundsException: -1 
    at java.lang.String.lastIndexOf(String.java:1889) 
    at java.lang.String.lastIndexOf(String.java:1835) 
    at java.lang.String.lastIndexOf(String.java:1817) 
    at com.acunia.service.position.nmea.comm.CommPositionProvider.isValid(Unknown Source) 

La linea che causa questa eccezione è:

int csi = line.lastIndexOf("*"); 

ho dato un'occhiata alla fonte String.java OpenJDK, ma non sono riuscito a trovare un difetto a meno che le matrici potrebbero improvvisamente iniziare a cambiare dimensione dopo averle create.

L'unico riferimento online che potrei trovare correlato era come un bug openjdk: https://bugs.openjdk.java.net/browse/JDK-6817012. Questo bug è stato contrassegnato come "non è un problema", anche se durante la lettura non riesco davvero a capire se il problema menzionato non è riconosciuto come un bug, o se la persona che ha chiuso il bug non vede perché questo bug causerebbe problemi

Se qualcuno ha mai riscontrato un problema simile, mi farebbe molto piacere sentirlo. Così com'è, il problema è troppo instabile per tentare di risolverlo usando altre versioni di openjdk.

problema è stato visto su:

hardware: custom arm platform 
java version "1.6.0_31" 
OpenJDK Runtime Environment (IcedTea6 1.13.3) (6b31-1.13.3-1~deb7u1) 
OpenJDK Zero VM (build 23.25-b01, mixed mode) 
Linux 3.2.0 #1 Fri Jun 20 10:25:16 CEST 2014 armv7l GNU/Linux 
+3

Si utilizza Java 6. Java 7 appena raggiunto la fine della vita. Dovresti davvero aggiornare il tuo Java. – icza

+3

Il secondo esempio potrebbe essere spiegato facilmente se il carattere non appare nella stringa. In tal caso, lastIndexOf restituisce -1 e il reclamo riguarda l'utilizzo dell'indice -1. –

+0

Vorrei anche raccomandare l'aggiornamento di Java a 8 se possibile. E preferibilmente la versione Oracle. OpenJDK non mi ha dato altro che mal di testa. –

risposta

3

Si sta creando il nuovo String utilizzando byte[] array senza specificare il Charset. Quindi la mia ipotesi è che il set di caratteri predefinito del sistema sia cambiato e si vede il comportamento cambia. Suggerirei di specificare sempre il set di caratteri esplicitamente. Ad esempio:

return new String(buffer, 70, 16, "UTF-8"); 
+0

Abbiamo esaminato questa possibilità. Il sistema è principalmente di sola lettura, quindi il set di caratteri predefinito non può essere stato modificato. Inoltre, se fosse stato cambiato, il problema sarebbe stato visto in molti punti, durante l'intera esecuzione abbiamo visto solo un'occorrenza di tale eccezione. Infine, il metodo checkBounds in java.lang.String sembra controllare solo in base alla dimensione dell'array di byte, non tiene conto di charset. –

+0

Il set di caratteri potrebbe non essere cambiato, ma forse l'input al sistema che l'ha attivato non si è verificato molto spesso? – aioobe

+0

L'input è attivato circa 4 volte al secondo per questa particolare discussione. Altri thread sono attivati ​​ancora più frequenti. –

4

Questo è molto probabilmente un problema con i byte e il set di caratteri di sistema. The documentation dice esplicitamente:

Il comportamento di questo costruttore quando i byte indicate non sono validi nella charset di default è non specificato.

È possibile aggirare questo fornendo esplicitamente il set di caratteri corretto:

new String(buffer, 70, 16, StandardCharsets.UTF_8) 
+0

(Per UTF-8 utilizzare 'StandardCharsets.UTF_8', non è necessario rilevare' UnsupportedEncodingException' perché i set di caratteri standard vengono sempre distribuiti con JRE.) –

+0

Nice. Non ero a conoscenza di quella classe. Aggiornato. Grazie. – aioobe

+0

Ho letto l'origine della classe String e sicuramente non ha nulla a che fare con i set di caratteri, (checkBounds viene chiamato prima di tentare di convertire i byte in caratteri). –

Problemi correlati