메모리에서 가장 큰 정수 배열을 유지하는 데 필요한 공간
알고리즘을 검토 중이며 정수 배열을 유지하며 입력 크기는 동적입니다. 그래서 내 계산에 따르면
integer MAX_VALUE * int size = ?
2^31 integers * 4 bytes = ?
2147483648 integers * 4 bytes = 8 Gigabytes
이 계산이 맞습니까? JVM은 int 배열을 저장하기 위해이 많은 연속 공간을 사용합니까 아니면 고려해야 할 다른 사항이 있습니까?
답변
배열의 이론적 크기는 다음과 같습니다.
numberOfElementsInTheArray * 4 바이트
12 바이트의 헤더 (
int[]
is an Object). 실제로 헤더의 크기는 사용한 플래그와 실행중인 JVM 버전에 따라 다릅니다.length
배열 을 유지하기위한 4 바이트심.
예를 들면 : (저는 이것을 위해 JOL 을 사용할 것입니다 ) :
int [] x = new int[10];
for(int i=0;i<10;++i){
x[i] = 9999;
}
System.out.println(GraphLayout.parseInstance((Object)x).toPrintable());
다음을 출력합니다.
[I@7a81197dd object externals:
ADDRESS SIZE TYPE PATH VALUE
70fe45268 56 [I [9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999]
그래서 그것은 56 bytes
:
- 값 자체의 경우 40 (정수 10 * 4 바이트)
- 헤더의 경우 12
- 길이 4
- 패딩의 경우 0
이 배열을로 변경하면 Integer
상황이 크게 변경됩니다. Integer
은 Object이므로 배열 ( 플래그 에 따라 4
또는 8
바이트 일 수 있음) 내에 참조를 저장하고 UseCompressedOops
각 Integer
인스턴스에는 2 개의 헤더가 필요합니다 (각각 Integer
은 Object 임).
Integer[] y = new Integer[10];
for(int i=0;i<10;++i){
y[i] = 9999;
}
System.out.println(GraphLayout.parseInstance((Object)y).toFootprint());
다음과 같이 표시됩니다.
[Ljava.lang.Integer;@369f73a2d footprint:
COUNT AVG SUM DESCRIPTION
1 56 56 [Ljava.lang.Integer;
10 16 160 java.lang.Integer
11 216 (total)
총 216 bytes
:
- 각 참조에 대해 4 바이트 (
UseCompressedOop
켜짐), 총 40 바이트 - 배열의 12 바이트 헤더
- 배열의 4 바이트 길이
- 0 바이트 패딩
해당 배열의 각 참조는를 가리키고 Integer
각 객체는 다음을 갖습니다 16 bytes
.
- 내부에 4 바이트
int
가 개최 - 12 바이트 헤더
- 0 바이트 패딩
최대 어레이 크기 < Integer.MAX_VALUE
아니요, 최대 값이 잘못되었습니다.
Java에서 배열의 요소 수에 대한 제한 Integer.MAX_VALUE은 Java 버전, 호스트 OS 및 Java 컴파일 방법에 따라 (2,147,483,647) 보다 약간 적습니다 . 질문에 Ivan Mamontov의 답변 을 참조하십시오 . 왜 큰 크기의 어레이를 만들 수 없습니까? .
예, int
≈ 8 기가 바이트의 가장 큰 어레이
따라서의 최대 배열 크기는 int
대략 ( Integer.MAX_VALUE - 8L ) * 32L
68,719,476,448 비트 인 8,589,934,556 옥텟 인 비트입니다.
예, 약 8 기가의 메모리입니다. 그리고 기억하세요 : 이것은 배열에 대한 연속적인 메모리입니다. 그래서:
- 런타임 중 해당 순간에 메모리가 얼마나 조각화되어 있는지에 따라 이러한 어레이를 생성하기 위해 JVM 및 호스트 OS 부분에서 상당한 작업이있을 수 있습니다 .
- 호스트 하드웨어에 실제 메모리가 충분하지 않으면 결과적인 페이징으로 인해 성능이 저하 될 수있는 가상 메모리로 이동하게됩니다.
작업에서 이러한 한계를 정말로 밀어 붙이고 있다면 항상 실제 테스트를 수행하십시오. 그리고 Azul Systems의 Zing 과 같이 매우 큰 메모리 용으로 설계된 Java의 대체 구현을 고려할 수 있습니다 .