Java: int dizisi sıfırdan farklı öğelerle başlar


130

JLS'ye göre, bir intdizi başlatıldıktan hemen sonra sıfırlarla doldurulmalıdır. Ancak olmadığı bir durumla karşı karşıyayım. Böyle bir davranış ilk olarak JDK 7u4'te ve sonraki tüm güncellemelerde de ortaya çıkar (64 bit uygulama kullanıyorum). Aşağıdaki kod istisna atar:

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

JVM kod bloğunu derledikten sonra istisna oluşur ve -Xintbayrakla ortaya çıkmaz . Ek olarak, Arrays.fill(...)ifade (bu koddaki diğer tüm ifadeler gibi) gereklidir ve yoksa istisna oluşmaz. Bu olası hatanın bazı JVM optimizasyonlarıyla sınırlı olduğu açıktır. Böyle bir davranışın nedeni için herhangi bir fikriniz var mı?

Güncelleme:
Bu davranışı HotSpot 64-bit sunucu VM'de, Gentoo Linux'ta 1.7.0_04'ten 1.7.0_10'a kadar Java sürümünde, Debian Linux'ta (her iki çekirdek 3.0 sürümü) ve MacOS Lion'da görüyorum. Bu hata her zaman yukarıdaki kodla çoğaltılabilir. Bu sorunu 32 bit JDK veya Windows üzerinde test etmedim. Oracle'a zaten bir hata raporu gönderdim (hata kimliği 7196857) ve birkaç gün içinde genel Oracle hata veritabanında görünecek.

Güncelleme:
Oracle bu hatayı genel hata veritabanında yayınladı: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7196857


15
Spesifikasyona
uymuyorsa

12
Sorunu güvenilir bir şekilde yeniden üreten iyi tanımlanmış bir örneğiniz olduğuna göre (en azından bazı platformlarda), bir hatayı doldurmayı düşündünüz mü?
Joachim Sauer

4
Evet, kesinlikle bir hata raporu vermelisiniz. Bu çok ciddi bir hata!
Hot Licks

7
Evet, Oracle'a zaten bir hata raporu gönderdim (hata kimliği 7196857) ve birkaç gün içinde genel Oracle hata veritabanında görünecek.
Stanislav Poslavsky

6
Windows'ta Java 7 güncelleme 7 64-bit ile denedim ve bir sorun yaşamadım.
Peter Lawrey

Yanıtlar:


42

Burada JIT derleyicisinde bir hata ile karşı karşıyayız. Derleyici, ayrılan dizinin içinde ayırma işleminden sonra doldurulduğunu belirler.Arrays.fill(...) , ancak ayırma ile dolgu arasındaki kullanımların kontrolü hatalı. Bu nedenle, derleyici geçersiz bir optimizasyon gerçekleştirir - tahsis edilen dizinin sıfırlanmasını atlar.

Bu hata Oracle hata izleyicisine ( hata kimliği 7196857 ) yerleştirilmiştir. Maalesef aşağıdaki noktalar hakkında Oracle'dan herhangi bir açıklama beklemedim. Gördüğüm gibi, bu hata işletim sistemine özgüdür: 64 bit Linux ve Mac'te kesinlikle yeniden üretilebilir, ancak yorumlardan gördüğüm gibi, Windows'ta düzenli olarak çoğalmıyor (JDK'nın benzer sürümleri için). Ek olarak, bu hatanın ne zaman düzeltileceğini bilmek güzel olurdu.

Şu anda sadece tavsiye var: Yeni bildirilen diziler için JLS'ye bağlıysanız, JDK1.7.0_04 veya sonrasını kullanmayın.

5 Ekim'de güncelleme:

04 Ekim 2012'de piyasaya sürülen JDK 7u10'un (erken erişim) yeni Build 10'unda , bu hata en azından Linux işletim sistemi için düzeltildi (diğerlerini test etmedim). Bu hatanın Oracle hata veritabanında artık halka açık olmadığını tespit eden @ Makoto'ya teşekkürler. Maalesef, Oracle'ın onu genel erişimden kaldırmasının nedenlerini bilmiyorum, ancak Google önbelleğinde mevcut . Ayrıca, bu hata Redhat'in dikkatini çekti: CVE tanımlayıcıları CVE-2012-4420 ( bugzilla ) ve CVE-2012-4416 ( bugzilla ) bu kusura atandı.


2
Hata kimliği artık geçersiz - buna bakabilir misiniz?
Makoto

1
@Makoto Kafam karıştı, çünkü bu hata dün hata veritabanındaydı. Oracle'ın bu hatayı genel erişimden kaldırmasının nedenini bilmiyorum. Ancak Google, webcache.googleusercontent.com/… 'yi hatırlıyor . Ek olarak, bu hata bir CVE'ye yol açabileceğinden RedHat hata veritabanına da yerleştirildi bugzilla.redhat.com/show_bug.cgi?id=856124
Stanislav Poslavsky

0

Kodunuzda bazı değişiklikler yaptım. Bu bir Tamsayı taşması sorunu değil. Koda bakın, çalışma zamanında bir istisna atıyor

    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 64 bit. Jdk 64 bit 1.7.0_07
Roberto Mereghetti
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.