Java: int 배열이 0이 아닌 요소로 초기화됨
JLS에 따르면int
어레이는 초기화 직후에 0으로 채워져야 합니다.그러나 나는 그렇지 않은 상황에 직면해 있다.이러한 동작은 JDK 7u4에서 먼저 발생하고 이후 모든 업데이트에서도 발생합니다(64비트 구현 사용).다음 코드는 예외를 발생시킵니다.
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이 코드 블록 컴파일을 수행한 후에 발생하며, 다음 코드 블록에서는 발생하지 않습니다.-Xint
flag. 또한,Arrays.fill(...)
스테이트먼트(이 코드의 다른 모든 스테이트먼트와 마찬가지로)가 필요하며, 이것이 존재하지 않는 경우 예외는 발생하지 않습니다.이 버그가 JVM 최적화에 의해 제한되고 있는 것은 분명합니다.왜 그런 행동을 했는지 짐작 가는 게 있나요?
업데이트:
Gentoo Linux, Debian Linux(커널 3.0 버전 모두) 및 MacOS Lion의 HotSpot 64비트 서버 VM, Java 버전 1.7.0_04 ~ 1.7.0_10에서 이 동작을 볼 수 있습니다.이 에러는, 항상 상기의 코드로 재현할 수 있습니다.32비트 JDK 또는 Windows에서는 이 문제를 테스트하지 않았습니다.저는 이미 Oracle(버그 ID 7196857)에 버그 보고서를 보냈고, 며칠 후에 공개 Oracle 버그 데이터베이스에 표시됩니다.
업데이트:
Oracle은 이 버그를 공개 버그 데이터베이스에 공개했습니다.http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7196857
여기에서는 JIT 컴파일러의 버그가 있습니다.컴파일러는 할당된 배열이 다음에서 할당된 후 채워지는 것을 확인합니다.Arrays.fill(...)
그러나 할당과 채우기 사이의 사용 확인에 오류가 있습니다.따라서 컴파일러는 잘못된 최적화를 수행합니다. 즉, 할당된 배열의 영점을 건너뜁니다.
이 버그는 Oracle 버그 트래커(버그 ID 7196857)에 있습니다.유감스럽게도, 저는 다음 사항에 대한 Oracle의 해명을 기다리지 않았습니다.이 버그는 OS에 따라 다릅니다.64비트 Linux 및 Mac에서는 절대 재현할 수 있습니다만, 코멘트에서 알 수 있듯이 Windows에서는 정기적으로 재현되지 않습니다(동일한 버전의 JDK의 경우).또, 이 버그가 언제 수정되는지 알고 싶습니다.
현시점에서는, 새롭게 선언된 어레이에 JLS 를 사용하고 있는 경우는, JDK1.7.0_04 이후를 사용하지 말아 주세요.
10월 5일 갱신:
2012년 10월 4일에 출시된 JDK 7u10의 새로운 빌드 10(얼리 액세스)에서는 적어도 Linux OS에서는 이 버그가 수정되었습니다(다른 버그는 테스트하지 않았습니다).@Makoto 덕분에 이 버그는 Oracle 버그 데이터베이스에서 더 이상 일반에 접근할 수 없게 되었습니다.아쉽게도 Oracle이 공개 접근에서 삭제한 이유는 알 수 없지만 Google 캐시에서 사용할 수 있습니다.또한 이 오류는 Redhat의 주의를 끌었습니다.CVE ID CVE-2012-4420(bugzilla) 및 CVE-2012-4416(bugzilla)이 이 장애에 할당되어 있습니다.
코드를 조금 변경했습니다.정수 오버플로 문제가 아닙니다.코드를 보면 실행 시 예외가 발생합니다.
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++;
}
언급URL : https://stackoverflow.com/questions/12317668/java-int-array-initializes-with-nonzero-elements
'source' 카테고리의 다른 글
지정된 유형의 컬렉션을 암시하는 형식 (0) | 2022.09.11 |
---|---|
Ubuntu에 MariaDB 설치: "패키지를 찾을 수 없습니다." (0) | 2022.09.11 |
누락된 상위 디렉토리와 함께 새 파일을 만드는 방법은 무엇입니까? (0) | 2022.09.11 |
Larabel 5 PDOException에서 드라이버를 찾을 수 없음 (0) | 2022.09.11 |
PHP와 함께 JSON POST 수신 (0) | 2022.09.11 |