Java: int array inizializzato con elementi diversi da zero


130

Secondo JLS, un intarray dovrebbe essere riempito di zeri subito dopo l'inizializzazione. Tuttavia, mi trovo di fronte a una situazione in cui non lo è. Tale comportamento si verifica prima in JDK 7u4 e si verifica anche in tutti gli aggiornamenti successivi (utilizzo l'implementazione a 64 bit). Il codice seguente genera un'eccezione:

public static void main(String[] args) {
        int[] a;
        int n = 0;
        for (int i = 0; i < 100000000; ++i) {
            a = new int[10];
            for (int f : a)
                if (f != 0)
                  throw new RuntimeException("Array just after allocation: "+ Arrays.toString(a));
            Arrays.fill(a, 0);
            for (int j = 0; j < a.length; ++j)
                a[j] = (n - j)*i;
            for (int f : a)
                n += f;
        }
        System.out.println(n);
    }

L'eccezione si verifica dopo che JVM ha eseguito la compilazione del blocco di codice e non si presenta con -Xintflag. Inoltre, l' Arrays.fill(...)istruzione (come tutte le altre istruzioni in questo codice) è necessaria e l'eccezione non si verifica se è assente. È chiaro che questo possibile bug è limitato da alcune ottimizzazioni JVM. Qualche idea sulla ragione di un simile comportamento?

Aggiornamento:
vedo questo comportamento sulla VM del server HotSpot 64-bit, versione Java da 1.7.0_04 a 1.7.0_10 su Gentoo Linux, Debian Linux (sia versione kernel 3.0) che MacOS Lion. Questo errore può sempre essere riprodotto con il codice sopra. Non ho provato questo problema con un JDK a 32 bit o su Windows. Ho già inviato una segnalazione di bug a Oracle (ID bug 7196857) e apparirà nel database di bug Oracle pubblico in pochi giorni.

Aggiornamento:
Oracle ha pubblicato questo bug nel proprio database pubblico di bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7196857


15
Direi bug nell'implementazione se non segue le specifiche
Petesh

12
Dato che hai un esempio ben definito che riproduce in modo affidabile il problema (almeno su alcune piattaforme), hai considerato di presentare un bug ?
Joachim Sauer,

4
Sì, dovresti assolutamente presentare una segnalazione di bug. Questo è un bug molto serio!
Hot Licks

7
Sì, ho già inviato una segnalazione di bug a Oracle (ID bug 7196857) e apparirà nel database di bug Oracle pubblico tra qualche giorno.
Stanislav Poslavsky,

6
L'ho provato con Java 7 Update 7 a 64 bit su Windows e non ha avuto problemi.
Peter Lawrey,

Risposte:


42

Qui ci troviamo di fronte a un bug nel compilatore JIT. Il compilatore determina che l'array allocato viene riempito dopo l'allocazione Arrays.fill(...), ma il controllo degli usi tra allocazione e riempimento è errato. Quindi, il compilatore esegue un'ottimizzazione illegale: salta l'azzeramento dell'array allocato.

Questo bug viene inserito nel tracker dei bug Oracle ( ID bug 7196857 ). Sfortunatamente, non ho aspettato alcun chiarimento da parte di Oracle sui seguenti punti. Come vedo, questo bug è specifico del sistema operativo: è assolutamente riproducibile su Linux e Mac a 64 bit, ma, come vedo dai commenti, non si riproduce regolarmente su Windows (per versioni simili di JDK). Inoltre sarebbe bello sapere quando questo bug verrà corretto.

Al momento sono disponibili solo consigli: non utilizzare JDK1.7.0_04 o successivo se si dipende da JLS per gli array appena dichiarati.

Aggiornamento al 5 ottobre:

Nel nuovo Build 10 del JDK 7u10 (accesso anticipato) rilasciato il 4 ottobre 2012, questo bug è stato corretto almeno per il sistema operativo Linux (non ho testato per altri). Grazie a @Makoto, che ha scoperto che questo errore non è più disponibile per l'accesso pubblico nel database degli errori Oracle. Sfortunatamente, non lo so per i motivi per cui Oracle l'ha rimosso dall'accesso pubblico, ma è disponibile nella cache di Google . Inoltre, questo bug ha attirato l'attenzione di Redhat: gli identificatori CVE CVE-2012-4420 ( bugzilla ) e CVE-2012-4416 ( bugzilla ) sono stati assegnati a questo difetto.


2
L'ID bug ora non è valido: potresti esaminarlo?
Makoto,

1
@Makoto Sono confuso, poiché ieri questo bug era nel database dei bug. Non so per quale motivo Oracle abbia rimosso questo bug dall'accesso pubblico. Ma Google ricorda webcache.googleusercontent.com/… Inoltre questo bug è stato inserito anche nel database dei bug di RedHat, poiché può portare a un CVE bugzilla.redhat.com/show_bug.cgi?id=856124
Stanislav Poslavsky

0

Ho apportato alcune modifiche al tuo codice. Non è un problema di overflow di numeri interi. Vedi il codice, genera un'eccezione in fase di esecuzione

    int[] a;
    int n = 0;
    for (int i = 0; i < 100000000; ++i) {
        a = new int[10];
        for (int f : a) {
            if (f != 0) {
                throw new RuntimeException("Array just after allocation: " + Arrays.toString(a));
            }
        }
        for (int ii = 0, len = a.length; ii < len; ii++)
            a[ii] = 0;
        for (int j = 0; j < a.length; ++j)
            a[j] = Integer.MAX_VALUE - 1;
        for (int j = 0; j < a.length; ++j)
            n++;
    }

Windows 7 a 64 bit. Jdk 64 bit 1.7.0_07
Roberto Mereghetti,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.