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


804

JUnit 테스트를 실행할 때이 오류 메시지가 나타납니다.

java.lang.OutOfMemoryError: GC overhead limit exceeded

나는 무엇인지 알고 OutOfMemoryError있지만 GC 오버 헤드 제한은 무엇을 의미합니까? 이 문제를 어떻게 해결할 수 있습니까?


16
이것은 매우 흥미로운 것 같습니다. 누군가 이것을 생성하는 코드를 게시 할 수 있다면 좋겠습니다.
Buhb

1
나는 단순히 힙의 한계에 가까운 메모리 사용량을 유발하는 문제를 발견했습니다. 간단한 해결책은 단순히 Java-Engine (-Xmx)에 더 많은 힙 메모리를 제공하는 것일 수 있지만 응용 프로그램이 이전의 힙 한계와 같이 정확히 많은 메모리가 필요한 경우에만 도움이됩니다.
Mnementh

1
@Mnementh 나는 여기에 stackoverflow.com/questions/11091516/…
lulu

16
@SimonKuang OutOfMemoryError힙을 늘리는 것이 유효한 솔루션이 아닌 여러 시나리오가 있습니다. 기본 스레드 부족 및 힙과 분리 된 perm gen 부족이 두 가지 예입니다. 에 대해 지나치게 광범위한 진술을 할 때주의하십시오 OutOfMemoryErrors. 그것들을 일으킬 수있는 예상치 못한 다양한 것들이 있습니다.
Tim

3
이 문제를 어떻게 해결 했습니까?
Thorsten Niehues

답변:


763

이 메시지는 어떤 이유로 가비지 콜렉터가 과도한 시간 (기본적으로 프로세스의 모든 CPU 시간의 98 %)을 소비하고 각 실행에서 매우 적은 메모리 (기본적으로 힙의 2 %)를 복구 함을 의미합니다.

이것은 효과적으로 프로그램이 진행을 멈추고 가비지 수집 만 항상 실행 중임을 의미합니다.

아무런 작업도 수행하지 않고 애플리케이션이 CPU 시간을 흡수하지 못하도록하기 위해 JVM이이를 처리 Error하여 문제점을 진단 할 수 있습니다.

제가보기에 드문 경우는 일부 코드가 이미 메모리가 매우 제한된 환경에서 수많은 임시 객체와 약하게 참조 된 많은 톤을 생성하는 경우입니다.

다양한 Java 버전에서 사용할 수 있으며이 특정 문제에 대한 섹션이 포함 된 Java GC 튜닝 안내서를 확인하십시오.


9
다음과 같이 답을 요약하면 맞습니까? " 'Java 힙 공간 부족'오류와 같습니다. -Xmx로 더 많은 메모리를 제공하십시오." ?
Tim Cooper

58
@Tim : 아니요. 정확하지 않습니다. 더 많은 메모리를 제공 하면 문제를 줄일 있지만 , 코드를 살펴보고 왜 그렇게 많은 양의 가비지를 생성하는지, 왜 코드가 "메모리 부족"표시 바로 아래로 미끄러지는지 확인해야합니다. 종종 깨진 코드의 징조입니다.
Joachim Sauer 2016 년

8
고마워, 오라클은 실제로 데이터 마이그레이션에 그다지 좋지 않은 것 같습니다.
Joachim Sauer

151
"감사합니다. 오라클이 실제로 그렇게 좋지 않은 것 같습니다"
Rob Grant

3
@Guus : 여러 애플리케이션이 동일한 JVM에서 실행되는 경우 서로 쉽게 영향을 줄 수 있습니다. 어느 것이 잘못 작동하는지 알기가 어렵습니다. 애플리케이션을 별개의 JVM으로 분리하는 것이 가장 쉬운 솔루션 일 수 있습니다.
Joachim Sauer

215

오라클의 기사 "Java SE 6 HotSpot [tm] 가상 머신 가비지 콜렉션 튜닝" 에서 인용 :

과도한 GC 시간 및 OutOfMemoryError

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

편집 : 누군가 나보다 빨리 입력 할 수있는 것처럼 보입니다 :)


87
"이 기능을 해제 할 수 있습니다 ..."그러나 OP는이 작업을 수행하지 않아야합니다.
Stephen C

2
"-XX"와 "-Xmx"의 차이점을 말씀해 주시겠습니까? "-Xmx"옵션을 사용하여 끌 수도있었습니다.
Susheel Javadi

19
@Bart -XX:여러 명령 행 옵션의 시작 부분에이 옵션이 매우 VM 별로 다르고 불안정하다는 것을 나타내는 일종의 플래그입니다 (향후 버전에서는 통지없이 변경 될 수 있음). 어쨌든 -XX:-UseGCOverheadLimit플래그는 VM에게 GC 오버 헤드 제한 검사 (실제로는 "끄기")를 비활성화하도록 -Xmx명령 하지만 명령은 단순히 힙을 증가시킵니다. 후자의 경우 GC 오버 헤드 검사가 여전히 실행 중입니다 . 더 큰 힙 이 귀하의 경우 GC 스 래싱 문제 해결 한 것처럼 들립니다 (항상 도움이되는 것은 아닙니다).
Andrzej Doyle

1
내 응용 프로그램 (Talend에서 큰 Excel 파일 읽기)에서 작동하지 않았으며 다른 사용자의 설명이 이유를 이해합니다. 이것은 오류를 비활성화하지만 문제는 지속되며 응용 프로그램은 대부분의 시간을 GC 처리에 소비합니다. 우리 서버에는 충분한 RAM이 있으므로 Vitalii의 제안을 사용하여 힙 크기를 늘 렸습니다.
RobbZ

응용 프로그램이 데이터를 많이 사용하여 메모리를 지우고 데이터 유출을 피하는 것이 가장 좋은 방법이지만 시간이 필요한 경우 결국이 오류가 발생합니다.
Pievis 2019

89

프로그램에 메모리 누수 가없는 경우 다음을 시도하십시오.

  1. 예를 들어 힙 크기를 늘리십시오 -Xmx1g.
  2. 동시 낮은 일시 중지 수집기를 활성화합니다 -XX:+UseConcMarkSweepGC.
  3. 가능하면 기존 객체를 재사용하여 메모리를 절약하십시오.

필요한 경우 옵션 을 명령 줄 에 추가 하여 제한 검사 를 비활성화 할 수 있습니다 -XX:-UseGCOverheadLimit.


9
세 번째 조언에 동의하지 않습니다. 기존 객체를 재사용하면 메모리가 절약되지 않습니다 (오래된 객체를 누수하지 않으면 메모리가 절약 됨). "기존 객체를 재사용"하면 GC 압력이 완화됩니다. 그러나 항상 좋은 생각은 아닙니다. 현대의 GC에서는 오래된 물체가 새로운 물체를 가지고있는 상황을 피해야합니다. 지역성 가정을 깰 수 있기 때문입니다.
mcoolive

@mcoolive : 다소 고안된 예를 보려면 아래의 stackoverflow.com/a/5640498/4178262 에 대한 의견을 참조하십시오 . List루프 내 에서 객체를 만들면 GC가 22 번이 아닌 39 번 호출됩니다.
마크 스튜어트

45

일반적으로 코드입니다. 다음은 간단한 예입니다.

import java.util.*;

public class GarbageCollector {

    public static void main(String... args) {

        System.out.printf("Testing...%n");
        List<Double> list = new ArrayList<Double>();
        for (int outer = 0; outer < 10000; outer++) {

            // list = new ArrayList<Double>(10000); // BAD
            // list = new ArrayList<Double>(); // WORSE
            list.clear(); // BETTER

            for (int inner = 0; inner < 10000; inner++) {
                list.add(Math.random());
            }

            if (outer % 1000 == 0) {
                System.out.printf("Outer loop at %d%n", outer);
            }

        }
        System.out.printf("Done.%n");
    }
}

Windows 7 32 비트에서 Java 1.6.0_24-b07 사용.

java -Xloggc:gc.log GarbageCollector

그럼 봐 gc.log

  • BAD 방법을 사용하여 444 회 트리거
  • WORSE 방법을 사용하여 666 번 트리거
  • BETTER 방법을 사용하여 354 번 트리거

이제 이것은 최고의 테스트 나 최고의 디자인은 아니지만 그러한 루프를 구현하는 것 외에 다른 루프를 구현하거나 잘못 작동하는 기존 코드를 처리 할 때 새로운 코드를 생성하는 대신 객체를 재사용하도록 선택할 수 있습니다. 가비지 수집기가 방해가되는 횟수


12
"Triggered n times"라고 말하면 일반 GC가 n 번 발생했거나 OP에서보고 한 "GC 오버 헤드 한도 초과"오류가 n 번 발생했음을 의미합니까?
Jon Schneider

방금 java 1.8.0_91을 사용하여 테스트했지만 오류 / 예외가 발생하지 않았으며 "Triggered n times"는 gc.log파일 의 줄 수를 세는 것 입니다. 내 테스트는 전반적으로 훨씬 적은 횟수를 보여 주지만 BETTER의 경우 "Triggers"시간이 가장 적으며, 현재 BAD는 WORST보다 "나쁘다". 내 카운트 : 나쁜 : 26, 나쁜 : 22, 더 나은 21.
마크 스튜어트

방금 "WORST_YET"수정을 추가 List<Double> list하여 외부 루프 이전 이 아닌 외부 루프 를 정의하고 39 개의 가비지 콜렉션을 트리거했습니다.
마크 스튜어트

36

Java [8] Platform, Standard Edition 문제 해결 안내서 에 따른 오류의 원인 : (강조 및 줄 바꿈 추가)

[...] "GC 오버 헤드 한계 초과"는 가비지 콜렉터가 항상 실행 중이며 Java 프로그램이 매우 느리게 진행되고 있음을 나타냅니다.

가비지 콜렉션 후 Java 프로세스가 가비지 콜렉션을 수행하는 데 시간의 약 98 % 이상을 소비 하고 힙의 2 % 미만을 복구하고 있으며 마지막 5 (컴파일 시간 상수) 연속 가비지 인 경우 컬렉션이 java.lang.OutOfMemoryError있으면 a 가 발생합니다. [...]

  1. 현재 힙이 충분하지 않은 경우 힙 크기를 늘리십시오 .
  2. 힙 메모리를 늘린 후에도이 오류가 계속 발생하면 MAT (메모리 분석기 도구), Visual VM 등과 같은 메모리 프로파일 링 도구를 사용 하고 메모리 누수를 수정하십시오.
  3. JDK 버전을 최신 버전 (1.8.x) 또는 1.7.x 이상으로 업그레이드하고 G1GC 알고리즘을 사용하십시오. . G1 GC의 처리량 목표는 90 %의 응용 프로그램 시간과 10 %의 가비지 수집 시간입니다.
  4. -로 힙 메모리를 설정하는 것 외에도 Xms1g -Xmx2g시도하십시오

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

G1GC에 관한 몇 가지 관련 질문을 살펴보십시오


29

이 옵션을 설정하여 힙 크기를 약간 늘리십시오.

실행 → 구성 실행 → 인수 → VM 인수

-Xms1024M -Xmx2048M

Xms- 최소 한계

Xmx- 최대 한계


2
안드로이드 앱에는 arguments탭이 없습니다 ...이 작업을 수행하려면 어떻게해야합니까?
Blaze Tama

3
그 도구는 어떤 도구입니까? 그것은 이클립스 질문이 아니었다.
Michael Piefel

3
"최소 한도"는 없습니다. -Xms는 초기 크기입니다.
Diego Queiroz

1
설정할 수있는 최대 제한의 최대 값은 얼마입니까?
JPerk

14

나를 위해 다음 단계가 효과적이었습니다.

  1. 열려있는 eclipse.ini파일을
  2. 변화

    -Xms40m
    -Xmx512m

    -Xms512m
    -Xmx1024m
  3. 이클립스 다시 시작

여기를 봐


이 문제를 해결하는 가장 간단한 방법입니다. 감사합니다 :)
Hamza

1
jdev의 eclipse.ini 파일?
Abhinaba Basu

구성이 이것으로 변경 되어도 문제가 해결되지 않습니다.
zionpi

1
OP는 이클립스 질문을하지 않았다.
Michael Piefel

1
이 "답변"은 위의 질문에 대답하지 않습니다.
프라이 타그

13

이 시도

~을여십시오 build.gradle 파일을

  android {
        dexOptions {
           javaMaxHeapSize = "4g"
        }
   }

시뮬레이터에 적합합니다. 이것이 실제 장치에 어떤 영향을 미치는지 아십니까? 즉, 이것이 좋은 아이디어입니까 아니면 문제를 숨기고 있습니까? 감사.
Joshua Pinter

11

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

android {
        compileSdkVersion 25
        buildToolsVersion '25.0.1'

defaultConfig {
        applicationId "yourpackage"
        minSdkVersion 10
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }
dexOptions {
        javaMaxHeapSize "4g"
    }
}

그래, Gradle을 사용할 때 :)
Alex

4
이것이 그의 일반적인 질문 대한 해결책이라고 어떻게 생각할 수 있습니까? 힙 크기를 4g로 설정하면 Android facepalm 의 gradle 구성에서 완전히 임의적입니다 .
Julian L.

7

build.gradle (Module : app) 파일에서 javaMaxHeapsize를 늘리십시오.

dexOptions {
    javaMaxHeapSize "1g"
}

(이 줄을 gradle에 추가하십시오)

 dexOptions {
        javaMaxHeapSize "4g"
    }

3

Java 힙 크기 설명 (xms, xmx, xmn)

-Xms size in bytes

Example : java -Xms32m

Java 힙의 초기 크기를 설정합니다. 기본 크기는 2097152 (2MB)입니다. 값은 1024 바이트 (1KB)의 배수 여야합니다. -server 플래그는 기본 크기를 32M으로 증가시킵니다.

-Xmn size in bytes

Example : java -Xmx2m

Eden 생성을위한 초기 Java 힙 크기를 설정합니다. 기본값은 640K입니다. -server 플래그는 기본 크기를 2M으로 증가시킵니다.

-Xmx size in bytes

Example : java -Xmx2048m

Java 힙이 커질 수있는 최대 크기를 설정합니다. 기본 크기는 64M입니다. (-server 플래그는 기본 크기를 128M으로 증가시킵니다.) 최대 힙 한계는 약 2GB (2048MB)입니다.

Java 메모리 인수 (xms, xmx, xmn) 형식

Java 힙 크기를 설정할 때 MB는 "m"또는 "M"또는 GB는 "g"또는 "G"중 하나를 사용하여 메모리 인수를 지정해야합니다. "MB"또는 "GB"를 지정하면 설정이 작동하지 않습니다. 유효한 인수는 다음과 같습니다.

-Xms64m 또는 -Xms64M -Xmx1g 또는 -Xmx1G 2048MB를 사용하여 2GB도 지정할 수 있습니다. 또한 인수를 지정할 때 정수만 사용해야합니다. -Xmx512m을 사용하는 것이 유효한 옵션이지만 -Xmx0.5g는 오류를 발생시킵니다.

이 참조는 누군가에게 도움이 될 수 있습니다.


2

gradle.properties파일에 이를 추가하여 메모리 할당 및 힙 크기를 늘릴 수도 있습니다.

org.gradle.jvmargs=-Xmx2048M -XX\:MaxHeapSize\=32g

2048M과 32g 일 필요는 없습니다. 원하는만큼 크게 만드십시오.


2

해결 :
추가
org.gradle.jvmargs=-Xmx1024m
하고
gradle.properties
존재하지 않는 경우 추가 하십시오.


0

Android Studio에서 작업 중이며 서명을 위해 서명 된 APK를 생성하려고 할 때이 오류가 발생했습니다. 문제없이 디버그 APK를 빌드하고 테스트 할 수 있었지만 릴리스 APK를 빌드하자마자 빌드 프로세스가 몇 분 동안 실행 된 다음 "Error java.lang.OutOfMemoryError : GC 오버 헤드 한도를 초과했습니다 ". VM과 Android DEX 컴파일러의 힙 크기를 늘 렸지만 문제는 계속되었습니다. 마지막으로 많은 시간과 커피를 마신 후에 문제가 앱 수준 'build.gradle'파일에 있음이 밝혀졌습니다. 릴리스 빌드 유형에 대한 'minifyEnabled'매개 변수가 'false'로 설정되어 결과적으로 Proguard 항목이 실행되었습니다. 코드 축소 프로세스를 거치지 않은 코드 https://developer.android). 'minifyEnabled'매개 변수를 'true'로 변경하고 릴리스 빌드가 꿈처럼 실행되었습니다. :)

요컨대, 앱 레벨 'build.gradle'파일을 다음과 같이 변경해야했습니다 : // ...

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.sign_config_release
    }
    debug {
        debuggable true
        signingConfig signingConfigs.sign_config_debug
    }
}

//...

    //...

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.sign_config_release
    }
    debug {
        debuggable true
        signingConfig signingConfigs.sign_config_debug
    }
}

//...

0

IntelliJ IDEA에서 힙 크기를 늘리려면 다음 지시 사항을 따르십시오. 그것은 나를 위해 일했다.

Windows 사용자의 경우

IDE가 설치된 위치로 이동하여 다음을 검색하십시오.

idea64.exe.vmoptions

파일을 편집하고 다음을 추가하십시오.

-Xms512m
-Xmx2024m
-XX:MaxPermSize=700m
-XX:ReservedCodeCacheSize=480m

그게 다야!


0

이 이미지를 참조하여 서버 설정을 변경하고 처리 프로세스 변경 사항의 메모리 크기를 노란색으로 강조 표시하여 증가시킬 수 있습니다.

set _java_opts -Xmx2g
프로그램의 복잡성에 따라 cmd- > 2g (2 기가 바이트) 를 열어 Java 힙을 변경할 수도 있습니다

덜 일정한 변수와 임시 변수를 사용하십시오

여기에 이미지 설명을 입력하십시오


-1

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**
)

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**

4
이 설정은 로컬 IDE에만 해당됩니다. Prod 환경에서는 작동하지 않습니다.
Feng

-1

Netbeans에서는 최대 힙 크기를 디자인하는 것이 도움이 될 수 있습니다. 실행 => 프로젝트 구성 설정 => 사용자 정의로 이동 하십시오 . 에서 실행 의 팝업 창으로 이동 VM 옵션 에 채우기 -Xms2048m -Xmx2048m. 힙 크기 문제를 해결할 수 있습니다.


-1

MacBook을 재부팅하면이 문제가 해결되었습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.