해시 맵에 50,000 개 객체를 삽입 할 때 왜 제외 시러를 얻습니까?

StackOverflow https://stackoverflow.com/questions/235047

  •  04-07-2019
  •  | 
  •  

문제

나는 약 50,000 개의 물체 (및 50,000 키)를 java.util.HashMap<java.awt.Point, Segment>. 그러나 나는 계속해서 메모리 예외를 얻고 있습니다. (Segment 내 자신의 수업입니다 - 매우 가벼운 무게 - 하나 String 필드 및 3 int 필드).

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.HashMap.resize(HashMap.java:508)
    at java.util.HashMap.addEntry(HashMap.java:799)
    at java.util.HashMap.put(HashMap.java:431)
    at bus.tools.UpdateMap.putSegment(UpdateMap.java:168)

가상 메모리를위한 무료 RAM과 HD 공간 모두에서 기계에 많은 메모리가 있다는 것을 알기 때문에 이것은 매우 우스운 것처럼 보입니다.

Java가 엄격한 메모리 요구 사항으로 실행 중일 가능합니까? 이것들을 늘릴 수 있습니까?

이상한 제한이 있습니까? HashMap? 내 자신을 구현해야할까요? 볼 가치가있는 다른 수업이 있습니까?

(2GB RAM이있는 인텔 머신에서 OS X 10.5에서 Java 5를 실행하고 있습니다.)

도움이 되었습니까?

해결책

-xmx128m (128은 메가 바이트 수)를 Java로 전달하여 최대 힙 크기를 늘릴 수 있습니다. 나는 기본 크기를 기억할 수 없지만 그것이 다소 작은 것이라는 사실을 알게됩니다.

프로그래밍 방식으로 사용하여 사용할 수있는 메모리를 확인할 수 있습니다. 실행 시간 수업.

// Get current size of heap in bytes
long heapSize = Runtime.getRuntime().totalMemory();

// Get maximum size of heap in bytes. The heap cannot grow beyond this size.
// Any attempt will result in an OutOfMemoryException.
long heapMaxSize = Runtime.getRuntime().maxMemory();

// Get amount of free memory within the heap in bytes. This size will increase
// after garbage collection and decrease as new objects are created.
long heapFreeSize = Runtime.getRuntime().freeMemory();

(예제 Java 개발자 Almanac)

이것은 부분적으로 다루어집니다 Java Hotspot VM에 대해 자주 묻는 질문, 그리고, 그리고 Java 6 GC 튜닝 페이지.

다른 팁

어떤 사람들은 메모리 요구 사항을 강화하기 위해 해시 맵의 매개 변수를 변경할 것을 제안하고 있습니다. 나는 제안 할 것이다 추측 대신 측정하십시오; Oome을 일으키는 다른 것일 수 있습니다. 특히 어느 쪽이든 사용하는 것이 좋습니다 Netbeans Profiler 또는 VisualVM (Java 6과 함께 제공되지만 Java 5에 갇힌 것을 본다).

객체의 수를 미리 알고 있다면 시도해야 할 또 다른 것은 (16,0.75)의 기본값을 사용하는 기본값 No-ARG ONE 대신 해시 맵 (int faruble, double loadfactor) 생성자를 사용하는 것입니다. 해시 맵의 요소 수가 초과 (용량 * loadfactor)를 초과하면 해시 맵의 기본 배열이 다음 전원 2로 크기가 커지고 테이블이 다시 해싱됩니다. 이 배열에는 인접한 메모리 영역이 필요하므로 예를 들어 32768에서 65536 크기의 배열로 두 배가되는 경우 256kb 덩어리의 메모리가 필요하지 않습니다. 추가 할당 및 재사용 처벌을 피하려면 처음부터 더 큰 해시 테이블을 사용하십시오. 또한지도에 맞을만큼 큰 메모리 영역이 없을 가능성이 줄어 듭니다.

구현은 일반적으로 배열로 뒷받침됩니다. 배열은 고정 된 크기의 메모리 블록입니다. 해시 맵 구현은이 배열 중 하나의 데이터를 주어진 용량 (100 개 객체)으로 저장하여 시작합니다.

배열을 채우고 객체를 계속 추가하면 맵이 배열 크기를 비밀리에 늘리기 위해 필요한 맵을 추가합니다. 배열은 고정되어 있으므로 완전히 새로운 배열을 메모리에 만들어 현재 배열과 함께 약간 더 큽니다. 이것은 배열을 성장시키는 것으로 지칭됩니다. 그런 다음 이전 배열의 모든 항목이 새 배열로 복사되고 이전 배열에는 쓰레기가 수집되고 메모리가 어느 시점에서 해제되기를 희망합니다.

일반적으로 항목을 더 큰 배열로 복사하여 맵의 용량을 증가시키는 코드는 그러한 문제의 원인입니다. 기존 배열의 크기를 기반으로 새 배열의 크기를 결정하는 성장 또는 하중 계수를 사용하는 "멍청한"구현과 스마트 한 구현이 있습니다. 일부 구현은 이러한 매개 변수를 숨기고 일부는 항상 설정할 수는 없습니다. 문제는 설정할 수 없을 때 2와 같은 기본 부하 계수를 선택한다는 것입니다. 따라서 새 배열은 이전의 크기의 두 배입니다. 이제 50k지도의 백업 배열은 100k입니다.

하중 계수를 0.25로 줄일 수 있는지 확인하십시오. 이로 인해 더 많은 해시 맵 충돌이 발생하여 성능이 상처를 주지만 메모리 병목 현상을 치고 있어야합니다.

이 생성자를 사용하십시오.

(http://java.sun.com/javase/6/docs/api/java/util/hashmap.html#hashmap(int, 뜨다))

Java를 시작할 때 플래그 -xmx512m 이상을 설정해야 할 것입니다. 64MB가 기본값이라고 생각합니다.

추가 편집 : 객체가 실제로 프로파일 러와 함께 사용하는 메모리의 양을 알아 낸 후 약한 참조 또는 소프트 참조를 조사하여 실수로 가비지 수집기로부터 메모리 인질을 실수로 잡고 있지 않도록 할 수 있습니다. 당신은 더 이상 그들을 사용하지 않습니다.

또한 이것을 살펴볼 수도 있습니다.

http://java.sun.com/docs/hotspot/gc/

이 답변에는 Java가 메모리의 고정 크기를 가지며 구성된 최대 힙 크기를 넘어서 자라지 않는다는 의미입니다. 이것은 C와 다릅니다.

기본적으로 JVM은 제한된 힙 공간을 사용합니다. 한도는 JVM 구현에 따라 다르며 사용중인 JVM이 명확하지 않습니다. Windows 이외의 OS의 경우 2GB 이상의 기계의 32 비트 SUN JVM은 실제 메모리의 1/4, 또는 귀하의 경우 512MB의 기본 최대 힙 크기를 사용합니다. 그러나 "클라이언트"모드 JVM의 기본값은 최대 64MB의 최대 힙 크기에 불과하므로 실행할 수 있습니다. 다른 공급 업체의 JVM은 다른 기본값을 선택할 수 있습니다.

물론, 당신은 힙 제한을 -Xmx<NN>m 옵션 java, 어디 <NN> 힙의 메가 바이트 수입니다.

거친 추측으로, 해시 테이블은 약 16MB 만 사용해야하므로 힙에 다른 큰 물체가 있어야합니다. 당신이 사용할 수 있다면 Comparable a TreeMap, 그것은 약간의 기억을 절약 할 것입니다.

보다 "5.0 JVM의 인체 공학" 자세한 사항은.

Java 힙 공간은 기본적으로 제한되어 있지만 여전히 극단적으로 들립니다 (50000 세그먼트는 얼마나 큰지).

모든 것이 동일한 "슬롯"에 할당되기 때문에 세트의 배열과 같은 다른 문제가 있다고 생각합니다 (물론 성능에도 영향을 미칩니다). 그러나 포인트가 균일하게 분포 된 경우에는 거의 없습니다.

왜 당신이 트리 맵 대신 해시 맵을 사용하고 있는지 궁금합니다. 포인트는 2 차원이지만 비교 함수로 서브 클래스 한 다음 (n) 조회를 수행 할 수 있습니다.

무작위 사고 : 해시 맵과 관련된 해시 버킷은 특히 메모리 효율적이지 않습니다. 대안으로 Treemap을 시험해보고 여전히 충분한 성능을 제공하는지 확인할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top