Java: int mảng khởi tạo với các phần tử khác 0


130

Theo JLS, một intmảng nên được điền bởi các số 0 ngay sau khi khởi tạo. Tuy nhiên, tôi phải đối mặt với một tình huống mà nó không phải là. Một hành vi như vậy xảy ra đầu tiên trong JDK 7u4 và cũng xảy ra trong tất cả các bản cập nhật sau này (tôi sử dụng triển khai 64 bit). Đoạn mã sau ném ngoại lệ:

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

Ngoại lệ xảy ra sau khi JVM thực hiện biên dịch khối mã và không phát sinh với -Xintcờ. Ngoài ra, Arrays.fill(...)câu lệnh (như tất cả các câu lệnh khác trong mã này) là cần thiết và ngoại lệ không xảy ra nếu nó không có. Rõ ràng là lỗi có thể này bị ràng buộc với một số tối ưu hóa JVM. Bất kỳ ý tưởng cho lý do của một hành vi như vậy?

Cập nhật:
Tôi thấy hành vi này trên máy chủ HotSpot 64 bit, phiên bản Java từ 1.7.0_04 đến 1.7.0_10 trên Gentoo Linux, Debian Linux (cả phiên bản kernel 3.0) và MacOS Lion. Lỗi này luôn có thể được sao chép với mã ở trên. Tôi đã không kiểm tra vấn đề này với JDK 32 bit hoặc trên Windows. Tôi đã gửi báo cáo lỗi tới Oracle (id lỗi 7196857) và nó sẽ xuất hiện trong cơ sở dữ liệu lỗi công khai của Oracle sau vài ngày.

Cập nhật:
Oracle đã xuất bản lỗi này tại cơ sở dữ liệu lỗi công khai của họ: http://bugs.sun.com/bugdatabase/view_orms.do?bug_id=7196857


15
Tôi muốn nói lỗi trong quá trình triển khai nếu nó không tuân theo thông số kỹ thuật
Petesh

12
Vì bạn có một ví dụ được xác định rõ ràng tái tạo vấn đề một cách đáng tin cậy (ít nhất là trên một số nền tảng), bạn đã xem xét việc gửi lỗi chưa?
Joachim Sauer

4
Có, bạn chắc chắn nên nộp báo cáo lỗi. Đây là một lỗi rất nghiêm trọng!
Licks nóng

7
Có, tôi đã gửi báo cáo lỗi tới Oracle (id lỗi 7196857) và nó sẽ xuất hiện trong cơ sở dữ liệu lỗi công khai của Oracle sau vài ngày.
Stanislav Poslavsky

6
Tôi đã thử nó với bản cập nhật Java 7 7 64 bit trên Windows và nó không gặp vấn đề gì.
Peter Lawrey

Câu trả lời:


42

Ở đây chúng ta phải đối mặt với một lỗi trong trình biên dịch JIT. Trình biên dịch xác định rằng mảng được phân bổ được điền sau khi cấp phát Arrays.fill(...), nhưng kiểm tra việc sử dụng giữa phân bổ và điền bị lỗi. Vì vậy, trình biên dịch thực hiện tối ưu hóa bất hợp pháp - nó bỏ qua zeroing của mảng được phân bổ.

Lỗi này được đặt trong trình theo dõi lỗi của Oracle ( lỗi id 7196857 ). Thật không may, tôi đã không chờ đợi bất kỳ sự làm rõ nào từ Oracle về các điểm sau. Như tôi thấy, lỗi này là dành riêng cho hệ điều hành: nó hoàn toàn có thể tái tạo trên Linux và Mac 64 bit, nhưng, như tôi thấy từ các bình luận, nó tái tạo không thường xuyên trên Windows (đối với các phiên bản tương tự của JDK). Ngoài ra, thật tuyệt khi biết lỗi này sẽ được khắc phục.

Hiện tại chỉ có lời khuyên: không sử dụng JDK1.7.0_04 trở lên nếu bạn phụ thuộc vào JLS cho các mảng mới được khai báo.

Cập nhật ngày 5 tháng 10:

Trong bản Build 10 mới của JDK 7u10 (truy cập sớm) được phát hành vào ngày 04 tháng 10 năm 2012, lỗi này đã được sửa ít nhất cho HĐH Linux (tôi không kiểm tra bản khác). Cảm ơn @Makoto, người đã phát hiện ra rằng lỗi này không còn có sẵn để truy cập công khai trong cơ sở dữ liệu lỗi của Oracle. Thật không may, tôi không biết vì lý do Oracle loại bỏ nó khỏi truy cập công cộng, nhưng nó có sẵn trong bộ đệm của Google . Ngoài ra, lỗi này đã thu hút sự chú ý của Redhat: các định danh CVE CVE-2012-4420 ( bugzilla ) và CVE-2012-4416 ( bugzilla ) đã được gán cho lỗ hổng này.


2
ID lỗi hiện không hợp lệ - bạn có thể xem xét điều này không?
Makoto

1
@Makoto Tôi bối rối, vì lỗi này là trong cơ sở dữ liệu lỗi ngày hôm qua. Tôi không biết lý do Oracle loại bỏ lỗi này khỏi truy cập công cộng. Tuy nhiên, Google nhớ webcache.googleusercontent.com/... Ngoài ra lỗi này cũng được đặt trong cơ sở dữ liệu lỗi RedHat, vì nó có thể dẫn đến một CVE bugzilla.redhat.com/show_bug.cgi?id=856124
Stanislav Poslavsky

0

Tôi đã thực hiện một số thay đổi trong mã của bạn. Đây không phải là vấn đề về tràn Integer. Xem mã, nó ném một ngoại lệ trong thời gian chạy

    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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.