Java: le tableau int s’initialise avec des éléments non nuls

Selon le JLS, un tableau int doit être rempli par des zéros juste après l’initialisation. Cependant, je suis confronté à une situation où ce n’est pas le cas. Un tel comportement se produit d’abord dans JDK 7u4 et se produit également dans toutes les mises à jour ultérieures (j’utilise une implémentation 64 bits). Le code suivant lève une exception:

 public static void main(Ssortingng[] 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’exception se produit après que la JVM effectue la compilation du bloc de code et ne se présente pas avec l’ -Xint . En outre, l’ Arrays.fill(...) (comme toutes les autres instructions de ce code) est nécessaire et l’exception ne se produit pas si elle est absente. Il est clair que ce bogue possible est lié à une optimisation JVM. Des idées pour la raison d’un tel comportement?

Mettre à jour:
Je vois ce comportement sur la machine virtuelle serveur HotSpot 64 bits, la version Java 1.7.0_04 à 1.7.0_10 sur Gentoo Linux, Debian Linux (toutes deux version du kernel 3.0) et MacOS Lion. Cette erreur peut toujours être reproduite avec le code ci-dessus. Je n’ai pas testé ce problème avec un JDK 32 bits ou Windows. J’ai déjà envoyé un rapport de bogue à Oracle (numéro de bogue 7196857) et celui-ci apparaîtra dans la firebase database publique des bogues Oracle dans quelques jours.

Mettre à jour:
Oracle a publié ce bogue sur sa firebase database publique de bogues: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7196857

Ici, nous sums confrontés à un bogue dans le compilateur JIT. Le compilateur détermine que le tableau alloué est rempli après l’allocation dans Arrays.fill(...) , mais la vérification des utilisations entre l’allocation et le remplissage est erronée. Ainsi, le compilateur effectue une optimisation illégale – il ignore la mise à zéro du tableau alloué.

Ce bug est placé dans Oracle Bug Tracker ( ID de bogue 7196857 ). Malheureusement, je n’ai pas attendu d’Oracle pour obtenir des éclaircissements sur les points suivants. Comme je le vois, ce bogue est spécifique à l’OS: il est absolument reproductible sur Linux et Mac 64 bits, mais, comme je le vois dans les commentaires, il ne se reproduit pas régulièrement sous Windows (pour les versions similaires de JDK). En outre, il serait bon de savoir quand ce bogue sera corrigé.

Il n’y a que des conseils pour le moment: n’utilisez pas JDK1.7.0_04 ou une version ultérieure si vous dépendez de JLS pour les baies nouvellement déclarées.

Mise à jour au 5 octobre:

Dans la nouvelle version 10 du JDK 7u10 (access anticipé) publiée le 4 octobre 2012, ce bogue était corrigé au moins pour Linux (je n’ai pas testé pour d’autres). Merci à @Makoto, qui a constaté que ce bogue n’est plus disponible pour un access public dans la firebase database de bogues Oracle. Malheureusement, je ne sais pas pour les raisons pour lesquelles Oracle l’a retiré de l’access public, mais il est disponible dans le cache Google. De plus, ce bogue a attiré l’attention de Redhat: les identifiants CVE-2012-4420 ( bugzilla ) et CVE-2012-4416 ( bugzilla ) ont été affectés à cette faille.

J’ai fait quelques changements dans votre code. Ce n’est pas un problème de dépassement d’entier. Voir le code, il lève une exception à l’exécution

  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++; }