IT

java.lang.OutOfMemoryError : GC 오버 헤드 한계를 초과했습니다

lottoking 2020. 3. 8. 16:25
반응형

java.lang.OutOfMemoryError : GC 오버 헤드 한계를 초과했습니다


각각 몇 (15-20) 개의 텍스트 항목으로 여러 (수만) HashMap 객체를 만드는 프로그램 에서이 오류가 발생합니다. 이 문자열은 데이터베이스에 제출하기 전에 모두 소량으로 분류하지 않고 수집해야합니다.

Sun에 따르면, "가비지 수집에 너무 많은 시간이 소비되는 경우 : 총 시간의 98 % 이상이 가비지 수집에 소비되고 힙의 2 % 미만이 복구되면 OutOfMemoryError가 발생합니다." ".

분명히 명령 줄을 사용하여 인수를 JVM에 전달할 수 있습니다.

  • "-Xmx1024m"이상을 통해 힙 크기 늘리기 또는
  • "-XX : -UseGCOverheadLimit"를 통해 오류 검사를 모두 비활성화합니다.

첫 번째 방법은 잘 작동하고 두 번째 방법은 다른 java.lang.OutOfMemoryError로 끝나고 이번에는 힙에 관한 것입니다.

따라서 질문 : 특정 사용 사례 (예 : 여러 개의 작은 HashMap 객체)에 대한 프로그래밍 대안이 있습니까? 예를 들어 HashMap clear () 메서드를 사용하면 문제가 사라지지만 HashMap에 저장된 데이터도 사라집니다! :-)

이 문제는 StackOverflow관련 항목 에서도 설명 합니다.


프로세스를 원활하게 실행하기 위해 본질적으로 메모리가 부족합니다. 마음에 드는 옵션 :

  1. 언급 한대로 더 많은 메모리를 지정하고 -Xmx512m처음 과 같은 것을 시도하십시오
  2. HashMap가능하면 한 번에 더 작은 크기의 개체를 처리하여 처리
  3. 중복 된 문자열이 많은 경우에는 문자열을 사용 String.intern()하기 전에 사용 하십시오.HashMap
  4. HashMap(int initialCapacity, float loadFactor)생성자를 사용 하여 사례를 조정하십시오.

다음은 나를 위해 일했습니다. 다음 스 니펫을 추가하십시오.

dexOptions {
        javaMaxHeapSize "4g"
}

당신에게 build.gradle:

android {
    compileSdkVersion 23
    buildToolsVersion '23.0.1'

    defaultConfig {
        applicationId "yourpackage"
        minSdkVersion 14
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"

        multiDexEnabled true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    packagingOptions {

    }

    dexOptions {
        javaMaxHeapSize "4g"
    }
}

@takrl :이 옵션의 기본 설정은 다음과 같습니다.

java -XX:+UseConcMarkSweepGC

즉,이 옵션은 기본적으로 활성화되어 있지 않습니다. " +XX:UseConcMarkSweepGC" 옵션을 사용했다고 말하면 이 구문을 사용한다고 가정합니다.

java -XX:+UseConcMarkSweepGC

이는이 옵션을 명시 적으로 활성화했음을 의미합니다. Java HotSpot VM Options@이 문서 의 올바른 구문과 기본 설정


기록적으로 우리는 오늘 같은 문제를 겪었습니다. 이 옵션을 사용하여 수정했습니다.

-XX:-UseConcMarkSweepGC

이로 인해 가비지 수집에 사용 된 전략이 수정되어 문제가 사라졌습니다.


음 ... 다음 중 하나를 수행해야합니다.

  1. 이 작은 HashMap이 모두 필요하지 않도록 알고리즘 및 데이터 구조를 완전히 다시 생각하십시오.

  2. 필요에 따라 해시 맵을 메모리 안팎으로 페이징 할 수있는 파사드를 만듭니다. 간단한 LRU 캐시는 티켓 일 수 있습니다.

  3. JVM에 사용 가능한 메모리를 설정하십시오. 필요한 경우,이 짐승을 호스팅하는 시스템을 관리하는 경우 더 많은 RAM을 구입하는 것이 가장 빠른 솔루션 일 수 있습니다. 저는 대체 알고리즘 솔루션이 합리적인 기간 내에 생각 될 수있는 경우, 일반적으로 "더 많은 하드웨어를 던지십시오"솔루션의 팬이 아닙니다. 이러한 문제가 발생할 때마다 더 많은 하드웨어를 계속 투입하면 곧 수익 감소 법칙에 처하게됩니다.

어쨌든 실제로 무엇을하려고합니까? 실제 문제에 대한 더 나은 접근 방법이 있다고 생각합니다.


대체 HashMap 구현 ( Trove )을 사용하십시오 . 표준 Java HashMap의 메모리 오버 헤드는 12 배 이상입니다. 여기에서 자세한 내용을 읽을 수 있습니다 .


끝까지 기다리는 동안 전체 구조를 메모리에 저장하지 마십시오.

해시 맵 대신 데이터베이스의 임시 테이블에 중간 결과를 씁니다. 기능적으로 데이터베이스 테이블은 해시 맵과 동일합니다. 즉, 둘 다 데이터에 대한 키 액세스를 지원하지만 테이블은 메모리에 바인딩되지 않으므로 인덱스 된 테이블을 사용하십시오. 해시 맵

올바르게 수행하면 알고리즘이 변경 사항을 알 수 없어야합니다. 여기서는 클래스를 사용하여 테이블을 나타내며 해시 맵과 같은 put (key, value) 및 get (key) 메소드를 제공하는 것입니다.

중간 테이블이 완료되면 메모리 대신 필요한 SQL 문을 생성하십시오.


OutOfMemoryError가비지 콜렉션에 너무 많은 시간이 소비되면 병렬 콜렉터는 if 를 던집니다 . 특히, 총 시간의 98 % 이상이 가비지 콜렉션에 사용되고 힙의 2 % 미만이 복구되면 OutOfMemoryError발생합니다. 이 기능은 힙이 너무 작아서 진행률을 거의 또는 전혀 유지하지 않으면 서 애플리케이션이 장시간 실행되지 않도록 설계되었습니다. 필요한 경우 옵션 -XX:-UseGCOverheadLimit을 명령 줄 에 추가하여이 기능을 비활성화 할 수 있습니다 .


수십만 개의 해시 맵을 만드는 경우 실제로 필요한 것보다 훨씬 많은 것을 사용하고있을 것입니다. 큰 파일이나 그래픽으로 작업하지 않는 한 간단한 데이터를 저장해도 Java 메모리 제한이 오버플로되지 않아야합니다.

알고리즘을 다시 시도해야합니다. 이 경우 해당 주제에 대해 더 많은 도움을 제공하지만 문제의 상황에 대해 더 많이 제공 할 때까지 정보를 제공 할 수 없습니다.


당신이있는 경우 java8을 , 그리고 당신이 사용할 수있는 G1 쓰레기 수집기를 한 후 사용하여 응용 프로그램을 실행합니다 :

 -XX:+UseG1GC -XX:+UseStringDeduplication

이것은 G1에게 비슷한 문자열을 찾고 그중 하나만 메모리에 유지하도록 지시하고, 다른 하나는 메모리에있는 해당 문자열에 대한 포인터 일뿐입니다.

반복되는 문자열이 많은 경우에 유용합니다. 이 솔루션은 작동하거나 작동하지 않을 수 있으며 각 응용 프로그램에 따라 다릅니다.


https://blog.codecentric.de/en/2014/08/string-deduplication-new-feature-java-8-update-20-2/ http://java-performance.info/java- 에 대한 자세한 정보 문자열 중복 제거 /


Eclipse MAT 또는 VisualVM 과 같은 프로파일 도구를 사용하여 애플리케이션의 메모리 누수 수정

함께 JDK 1.7.x또는 이후 버전의 사용 G1GC, 다른 GC 알고리즘 2 % 달리 가비지 컬렉션에 10 %를 보낸다.

로 힙 메모리를 설정하는 것 외에도 -Xms1g -Xmx2g`

-XX:+UseG1GC 
-XX:G1HeapRegionSize=n, 
-XX:MaxGCPauseMillis=m, 
-XX:ParallelGCThreads=n, 
-XX:ConcGCThreads=n`

이러한 매개 변수를 미세 조정하는 오라클 기사를 살펴보십시오 .

SE의 G1GC와 관련된 몇 가지 질문 :

G1의 Java 7 (JDK 7) 가비지 콜렉션 및 문서

프로덕션에서 Java G1 가비지 콜렉션

적극적인 가비지 수집기 전략


오류가 발생한 경우 :

"내부 컴파일러 오류 : java.lang.OutOfMemoryError : java.lang.AbstractStringBuilder에서 GC 오버 헤드 한계를 초과했습니다."

자바 힙 공간을 2GB로 늘리십시오. -Xmx2g.


Jdeveloper에서 메모리 크기를 늘려야합니다. setDomainEnv.cmd로 이동하십시오.

set WLS_HOME=%WL_HOME%\server
set XMS_SUN_64BIT=256
set XMS_SUN_32BIT=256
set XMX_SUN_64BIT=3072
set XMX_SUN_32BIT=3072
set XMS_JROCKIT_64BIT=256
set XMS_JROCKIT_32BIT=256
set XMX_JROCKIT_64BIT=1024
set XMX_JROCKIT_32BIT=1024

if "%JAVA_VENDOR%"=="Sun" (
    set WLS_MEM_ARGS_64BIT=-Xms256m -Xmx512m
    set WLS_MEM_ARGS_32BIT=-Xms256m -Xmx512m
) else (
    set WLS_MEM_ARGS_64BIT=-Xms512m -Xmx512m
    set WLS_MEM_ARGS_32BIT=-Xms512m -Xmx512m
)
and

set MEM_PERM_SIZE_64BIT=-XX:PermSize=256m
set MEM_PERM_SIZE_32BIT=-XX:PermSize=256m

if "%JAVA_USE_64BIT%"=="true" (
    set MEM_PERM_SIZE=%MEM_PERM_SIZE_64BIT%

) else (
    set MEM_PERM_SIZE=%MEM_PERM_SIZE_32BIT%
)

set MEM_MAX_PERM_SIZE_64BIT=-XX:MaxPermSize=1024m
set MEM_MAX_PERM_SIZE_32BIT=-XX:MaxPermSize=1024m

이를 위해 안드로이드 클로저에서 앱 gradle 파일의 아래 코드를 사용하십시오.

dexOptions {javaMaxHeapSize "4g"}


필자의 경우 -Xmx옵션을 사용하여 메모리를 늘리는 것이 해결책이었습니다.

Java에서 10g 파일을 읽었으며 매번 같은 오류가 발생했습니다. 이것은 명령 RES열의 top값이 -Xmx 옵션에 설정된 값에 도달 했을 때 발생 했습니다. 그런 다음 -Xmx옵션을 사용하여 메모리를 늘리면 모든 것이 잘되었습니다.

또 다른 요점이있었습니다. JAVA_OPTS또는 CATALINA_OPTS사용자 계정을 설정 하거나 메모리 양을 다시 늘리면 동일한 오류가 발생합니다. 그런 다음 코드에서 환경 변수의 값을 인쇄하여 설정 한 것과 다른 값을 제공했습니다. 그 이유는 Tomcat이 해당 프로세스의 근본이었고 sudodo가 아니기 때문에 관리자에게 catalina.shTomcat 의 메모리를 늘리라고 요청했습니다 .


이 오류를 제거하는 데 도움이되었습니다.이 옵션은 -XX : + DisableExplicitGC를 비활성화합니다.

참고 URL : https://stackoverflow.com/questions/5839359/java-lang-outofmemoryerror-gc-overhead-limit-exceeded



반응형