Menurut JLS, int
array harus diisi dengan nol setelah inisialisasi. Namun, saya dihadapkan pada situasi di mana tidak. Perilaku seperti itu terjadi pertama kali di JDK 7u4 dan juga terjadi di semua pembaruan selanjutnya (saya menggunakan implementasi 64-bit). Kode berikut melempar pengecualian:
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);
}
Pengecualian terjadi setelah JVM melakukan kompilasi blok kode dan tidak muncul dengan -Xint
flag. Selain itu, Arrays.fill(...)
pernyataan (karena semua pernyataan lain dalam kode ini) diperlukan, dan pengecualian tidak terjadi jika tidak ada. Jelas bahwa kemungkinan bug ini terikat dengan beberapa optimasi JVM. Adakah ide untuk alasan perilaku seperti itu?
Memperbarui:
Saya melihat perilaku ini pada HotSpot 64-bit server VM, versi Java dari 1.7.0_04 ke 1.7.0_10 pada Gentoo Linux, Debian Linux (keduanya versi kernel 3.0) dan MacOS Lion. Kesalahan ini selalu dapat direproduksi dengan kode di atas. Saya tidak menguji masalah ini dengan JDK 32-bit atau pada Windows. Saya sudah mengirim laporan bug ke Oracle (bug id 7196857) dan akan muncul di database bug Oracle publik dalam beberapa hari.
Pembaruan:
Oracle menerbitkan bug ini di database bug publik mereka: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7196857
Jawaban:
Di sini kita dihadapkan dengan bug di JIT-compiler. Kompiler menentukan bahwa array yang dialokasikan diisi setelah alokasi masuk
Arrays.fill(...)
, tetapi pemeriksaan untuk penggunaan antara alokasi dan pengisian salah. Jadi, kompiler melakukan optimasi ilegal - ia melewatkan zeroing dari array yang dialokasikan.Bug ini ditempatkan di pelacak bug Oracle ( bug id 7196857 ). Sayangnya, saya tidak menunggu klarifikasi dari Oracle tentang poin-poin berikut. Seperti yang saya lihat, bug ini khusus untuk OS: benar-benar dapat diproduksi ulang di 64-bit Linux dan Mac, tetapi, seperti yang saya lihat dari komentar, bug ini tidak bereproduksi secara teratur di Windows (untuk versi JDK yang serupa). Selain itu akan menyenangkan untuk mengetahui kapan bug ini akan diperbaiki.
Hanya ada saran saat ini: jangan gunakan JDK1.7.0_04 atau lebih baru jika Anda bergantung pada JLS untuk array yang baru dideklarasikan.
Pembaruan pada 5 Oktober:
Dalam Build 10 baru dari JDK 7u10 (akses awal) dirilis pada 04 Oktober 2012, bug ini diperbaiki setidaknya untuk OS Linux (saya tidak menguji yang lain). Terima kasih kepada @Makoto, yang menemukan bahwa bug ini tidak lagi tersedia untuk akses publik di database bug Oracle. Sayangnya, saya tidak tahu karena alasan Oracle menghapusnya dari akses publik, tetapi itu tersedia di cache Google . Juga, bug ini telah menarik perhatian Redhat: pengidentifikasi CVE CVE-2012-4420 ( bugzilla ) dan CVE-2012-4416 ( bugzilla ) ditugaskan untuk cacat ini.
sumber
Saya membuat beberapa perubahan pada kode Anda. Ini bukan masalah Integer overflow. Lihat kode, itu melempar pengecualian pada saat runtime
sumber