메모리에서 가장 큰 정수 배열을 유지하는 데 필요한 공간

Jan 04 2021

알고리즘을 검토 중이며 정수 배열을 유지하며 입력 크기는 동적입니다. 그래서 내 계산에 따르면

  integer MAX_VALUE  * int size  = ?   
      2^31 integers  * 4 bytes   = ?
2147483648 integers  * 4 bytes   = 8 Gigabytes

이 계산이 맞습니까? JVM은 int 배열을 저장하기 위해이 많은 연속 공간을 사용합니까 아니면 고려해야 할 다른 사항이 있습니까?

답변

3 Eugene Jan 05 2021 at 01:39

배열의 이론적 크기는 다음과 같습니다.

  • 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바이트 일 수 있음) 내에 참조를 저장하고 UseCompressedOopsInteger인스턴스에는 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 바이트 패딩
1 BasilBourque Jan 04 2021 at 15:23

최대 어레이 크기 < Integer.MAX_VALUE

아니요, 최대 값이 잘못되었습니다.

Java에서 배열의 요소 수에 대한 제한 Integer.MAX_VALUE은 Java 버전, 호스트 OS 및 Java 컴파일 방법에 따라 (2,147,483,647) 보다 약간 적습니다 . 질문에 Ivan Mamontov의 답변 을 참조하십시오 . 왜 큰 크기의 어레이를 만들 수 없습니까? .

예, int≈ 8 기가 바이트의 가장 큰 어레이

따라서의 최대 배열 크기는 int대략 ( Integer.MAX_VALUE - 8L ) * 32L68,719,476,448 비트 인 8,589,934,556 옥텟 인 비트입니다.

예, 약 8 기가의 메모리입니다. 그리고 기억하세요 : 이것은 배열에 대한 연속적인 메모리입니다. 그래서:

  • 런타임 중 해당 순간에 메모리가 얼마나 조각화되어 있는지에 따라 이러한 어레이를 생성하기 위해 JVM 및 호스트 OS 부분에서 상당한 작업이있을 수 있습니다 .
  • 호스트 하드웨어에 실제 메모리가 충분하지 않으면 결과적인 페이징으로 인해 성능이 저하 될 수있는 가상 메모리로 이동하게됩니다.

작업에서 이러한 한계를 정말로 밀어 붙이고 있다면 항상 실제 테스트를 수행하십시오. 그리고 Azul Systems의 Zing 과 같이 매우 큰 메모리 용으로 설계된 Java의 대체 구현을 고려할 수 있습니다 .