"java.lang.OutOfMemoryError : Java heap space"오류를 처리하는 방법은 무엇입니까?


416

Java 5 에서 클라이언트 측 Swing 응용 프로그램 (그래픽 글꼴 디자이너)을 작성 중 입니다. 최근 메모리 사용량이 보수적이지 않아 오류가 발생했습니다. 사용자는 무제한으로 파일을 열 수 있으며 프로그램은 열린 개체를 메모리에 유지합니다. 빠른 연구 후 5.0 Java Virtual Machine 에서 Ergonomics를 발견 했으며 Windows 시스템에서 JVM의 최대 힙 크기는로 기본 설정되어 있습니다.java.lang.OutOfMemoryError: Java heap space64MB

이 상황 에서이 제약 조건을 어떻게 처리해야합니까?

커맨드 라인 옵션을 사용하여 최대 힙 크기 를 java로 늘릴 수 있지만 사용 가능한 RAM을 파악하고 시작 프로그램 또는 스크립트를 작성해야합니다. 게다가, 유한 한 최대 값으로 증가시키는 것이 궁극적으로 문제를 제거 하지는 않습니다 .

메모리를 비우기 위해 데이터베이스를 사용하는 객체를 파일 시스템에 자주 유지하기 위해 일부 코드를 다시 작성할 수 있습니다. 작동 할 수는 있지만 아마도 많은 작업 일 것입니다.

위의 아이디어에 대한 세부 사항이나 자동 가상 메모리 와 같은 일부 대안 , 힙 크기를 동적으로 확장 하는 방법을 알려 주면 좋을 것입니다.


64MB의 기본 최대 힙 크기는 J2SE 5.0 이전입니다. J2SE 8.0 정보는 docs.oracle.com/javase/8/docs/technotes/guides/vm/…의 "Garbage Collector Ergonomics"를 참조하십시오 .
Andy Thomas

모든 OOM 질문이이 질문으로 인해 여기에 착륙 한 경우 다음을 확인하십시오. stackoverflow.com/questions/299659/… OOM 전에 '적시에'메모리 참조를 정리하는 솔루션을 제공합니다. SoftReferences는 실제 문제를 해결하는 도구 일 수 있습니다.
Steve Steiner

답변:


244

궁극적으로 실행중인 플랫폼에 관계없이 항상 최대의 힙을 가지고 있습니다. Windows 32 비트에서 이것은 주변에 있습니다 2GB(특히 힙이 아니라 프로세스 당 총 메모리 양). Java가 기본값을 더 작게 선택하는 것만으로 발생합니다 (아마도 프로그래머 가이 문제를 겪지 않고 실행중인 메모리를 정확하게 검사하지 않고도 메모리 할당량이 많은 프로그램을 만들 수 없음).

따라서 필요한 메모리 양을 결정하거나 사용중인 메모리 양을 줄이기 위해 취할 수있는 몇 가지 방법이 있습니다. Java 또는 C #과 같은 가비지 수집 언어의 일반적인 실수 중 하나는 더 이상 사용 하지 않는 객체에 대한 참조를 유지 하거나 대신 재사용 할 수있을 때 많은 객체를 할당 하는 것입니다. 객체가 객체를 참조하는 한 가비지 수집기는 객체를 삭제하지 않으므로 힙 공간을 계속 사용합니다.

이 경우 Java 메모리 프로파일 러를 사용하여 프로그램에서 많은 수의 오브젝트를 할당하는 메소드를 판별 한 후 더 이상 참조되지 않는지 또는 우선 할당하지 않는 방법을 판별 할 수 있습니다. 과거에 사용한 한 가지 옵션은 "JMP" http://www.khelekore.org/jmp/ 입니다.

이유 때문에 이러한 오브젝트를 할당하고 참조를 유지해야하는 경우 (이 작업을 수행하는 경우에 따라 다름) 프로그램을 시작할 때 최대 힙 크기를 늘려야합니다. 그러나 메모리 프로파일 링을 수행하고 객체 할당 방법을 이해하면 필요한 메모리 양에 대해 더 잘 알고 있어야합니다.

일반적으로 프로그램이 유한 한 양의 메모리에서 (아마도 입력 크기에 따라) 실행될 것이라고 보장 할 수없는 경우 항상이 문제가 발생합니다. 이 모든 것을 다 사용한 후에 만 ​​객체를 디스크 등으로 캐싱해야합니다.이 시점에서 무언가를 위해 "Xgb의 메모리가 필요합니다"라고 말할만한 충분한 이유가 있어야하며 개선하여 해결할 수 없습니다. 알고리즘 또는 메모리 할당 패턴. 일반적으로 이는 데이터베이스 또는 과학적 분석 프로그램과 같은 대규모 데이터 세트에서 작동하는 알고리즘의 경우에만 해당되며 캐싱 및 메모리 매핑 IO와 같은 기술이 유용합니다.


6
OpenJDK 및 OracleJDK에는 프로파일 러 인 jvisualvm이 번들로 제공됩니다. 더 많은 편의를 원한다면 상업용 Yourkit을 제안하십시오.
Petr Gladkikh


85

프로젝트별로 원하는 힙 공간을 프로젝트별로 지정할 있습니다.

을위한 다음 이클립스 헬리오스 / 주노 / 케플러 :

마우스 오른쪽 클릭

 Run As - Run Configuration - Arguments - Vm Arguments, 

그런 다음 이것을 추가하십시오

-Xmx2048m

1
안녕하세요 bighostkim 및 cuongHuyTo, "Arguments"가 있습니다. 실행 구성까지 볼 수 있습니다. 전화주세요. Gmail에서 거의 2000 개의 연락처를 다운로드하여 저장해야합니다. 이 때문에 메모리 부족 예외로 충돌
AndroidRaji

@AndroiRaji : 실행 가능한 기본 ( "public static void main (String [] args)")이있는 Java 클래스를 마우스 오른쪽 단추로 클릭 한 후 실행 도구-실행 구성을 선택하십시오. "Arguments"는 Main 바로 다음에있는 탭입니다 (Main, Arguments, JRE, Classpath, Source, Environment, Common 탭이 나타납니다).
CuongHuyTo

47

힙 크기를 늘리는 것은 "수정"이 아니라 100 % 일시적인 "석고"입니다. 다른 곳에서 다시 충돌합니다. 이러한 문제를 피하려면 고성능 코드를 작성하십시오.

  1. 가능하면 지역 변수를 사용하십시오.
  2. 올바른 객체를 선택했는지 확인하십시오 (예 : String, StringBuffer 및 StringBuilder 사이의 선택)
  3. 프로그램에 적합한 코드 시스템을 사용하십시오 (예 : 정적 변수 사용 및 비 정적 변수 사용)
  4. 코드에서 작동 할 수있는 다른 것들.
  5. 멀티 스레딩으로 이동해보십시오

이건 정말 진실. AWT 스레드에서 OOM을 얻는 한 가지 문제를 해결하려고하지만 다른 새 스레드를 사용하면 OOM 문제가 발생하지 않습니다. 온라인에서 찾을 수있는 것은 AWT 스레드의 힙 크기를 늘리는 것입니다.
Ashish

@Ash : 그렇습니다. 석고를 찾는 대신 핵심 문제를 해결하십시오.
레몬 주스

Java의 가비지 수집 및 메모리 관리 접근 방식은 이전 모델의 malloc-dealloc 합병증을 모두 해결해야했습니다. 최대한 빨리 정리되는
Davos

31

큰 경고 ---- 내 사무실에서 (일부 Windows 시스템에서) Java 힙에 512m 이상을 할당 할 수 없다는 것을 발견했습니다. 이것은 일부 컴퓨터에 설치된 카스퍼 스키 안티 바이러스 제품 때문인 것으로 나타났습니다. 해당 AV 제품을 제거한 후 1.6GB 이상을 할당 할 수 있음을 발견했습니다. 즉, -Xmx1600mm은 다른 초기에는 "너무 작은 초기 힙"이라는 다른 오류가 발생합니다.

이것이 다른 AV 제품에서 발생하는지는 모르지만, 아마도 AV 프로그램이 모든 주소 공간에 작은 메모리 블록을 예약하여 실제로 단일 할당을 막기 때문에 발생하는 것 같습니다.


22

VM 인수는 일식에서 나를 위해 일했습니다. Eclipse 버전 3.4를 사용중인 경우 다음을 수행하십시오.

로 이동하여 Run --> Run Configurations -->maven build에서 프로젝트를 선택한 다음 "JRE"탭을 선택하고 입력하십시오 -Xmx1024m.

또는 Run --> Run Configurations --> select the "JRE" tab -->다음을 입력 해도됩니다.Xmx1024m

모든 빌드 / 프로젝트의 메모리 힙이 증가합니다. 위의 메모리 크기는 1GB입니다. 원하는 방식으로 최적화 할 수 있습니다.


18

예, -XmxJVM에 더 많은 메모리를 구성 할 수 있습니다. 메모리가 누출되거나 낭비되지 않도록하십시오. 힙 덤프를 가져와 Eclipse 메모리 분석기 를 사용하여 메모리 소비를 분석하십시오.


JVMJ9VM007E 명령 행 옵션을 인식 할 수 없습니다. -Xmx Java 가상 머신을 작성할 수 없습니다. Downvote
Philip Rego

17

오라클 문제 해결 에서 권장 사항을 추가하고 싶습니다 기사의 .

스레드 thread_name의 예외 : java.lang.OutOfMemoryError : Java 힙 공간

세부 사항 메시지 Java 힙 공간은 Java 힙에서 오브젝트를 할당 할 수 없음을 나타냅니다. 이 오류가 반드시 메모리 누수를 의미하지는 않습니다

가능한 원인들:

  1. 지정된 힙 크기가 응용 프로그램에 충분하지 않은 간단한 구성 문제

  2. 응용 프로그램이 실수로 객체에 대한 참조를 보유 하고 있으므로 객체가 가비지 수집되지 않습니다.

  3. 종료자를 과도하게 사용 합니다.

이 오류의 또 다른 잠재적 원인은 종료자를 과도하게 사용하는 응용 프로그램에서 발생합니다. 클래스에 finalize 메소드가있는 경우 해당 유형의 오브젝트는 가비지 콜렉션시 공간을 확보하지 않습니다.

가비지 수집 후 객체는 종료를 위해 큐에 대기되며 나중에 발생합니다. finalizer 는 finalization queue를 서비스하는 데몬 스레드에 의해 실행됩니다. 는 IF 종료 자 스레드가 마무리 큐와 함께 유지할 수 없다, 다음 Java 힙은 채울 수 있으며, 이러한 유형의 OutOfMemoryError가의 예외가 발생 될 것이다.

이 상황을 야기 할 수있는 한 가지 시나리오는 응용 프로그램이 우선 순위높은 스레드 를 작성 하여 종료 큐가 해당 큐를 서비스하는 속도보다 빠른 속도로 종료 큐를 증가시키는 경우입니다.


9

아래 단계를 수행하십시오.

  1. catalina.sh바람둥이 / 빈에서 엽니 다 .

  2. JAVA_OPTS를 다음으로 변경

    JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1536m 
    -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m 
    -XX:MaxPermSize=256m -XX:+DisableExplicitGC"
  3. 바람둥이를 다시 시작


8

java.lang.OutOfMemoryError를 catch하고 catch 블록에서 많은 메모리를 사용하고 연결을 닫는 등의 모든 리소스를 해제 한 다음 수행 할 수있는 다른 곳을 읽었습니다. System.gc() 다음 다시 시도하십시오. 당신은하려고했다.

또 다른 방법은 이것이 작동하는지 여부를 모르지만 현재 응용 프로그램에서 작동하는지 테스트하고 있습니다.

아이디어는 여유 메모리를 늘리는 것으로 알려진 System.gc ()를 호출하여 가비지 콜렉션을 수행하는 것입니다. 메모리 고 블링 코드가 실행 된 후에도이를 확인할 수 있습니다.

//Mimimum acceptable free memory you think your app needs
long minRunningMemory = (1024*1024);

Runtime runtime = Runtime.getRuntime();

if(runtime.freeMemory()<minRunningMemory)
 System.gc();

6
일반적으로 JVM은 OutOfMemoryError를 발생시키는 것이 아니라 GC (Garbage Collect)를 선호한다고 생각합니다. OutOfMemoryError 후에 명시 적으로 System.gc ()를 호출하면 일부 VM / 구성에서 도움이 될 수 있지만 일반적인 경우에는 잘 작동하지 않을 것으로 예상됩니다. 그러나 불필요한 객체 참조를 삭제하면 거의 모든 경우에 도움이 될 것입니다.
Mike Clark

6
@mwangi 코드에서 직접 System.gc ()를 호출하는 것은 일반적으로 나쁜 생각입니다. GC를 수행해야한다는 것은 JVM에 대한 제안 일 뿐이지 만 수행 될 것이라는 보장없습니다 .

7

OutOfMemoryErrorJava 에서 해결하는 쉬운 방법 은 JVM 옵션을 사용하여 최대 힙 크기를 늘리는 것입니다.-Xmx512M 것입니다. 그러면 OutOfMemoryError가 즉시 해결됩니다. 프로젝트의 크기에 따라 쉽게 메모리가 부족 할 수 있기 때문에 프로젝트를 빌드하는 동안 Eclipse, Maven 또는 ANT에서 OutOfMemoryError가 발생하면 선호하는 솔루션입니다.

다음은 JVM의 최대 힙 크기를 늘리는 예입니다. 또한 Java 애플리케이션에서 힙 크기를 설정하는 경우 -Xmx를 -Xms 비율로 1 : 1 또는 1 : 1.5로 유지하는 것이 좋습니다.

export JVM_ARGS="-Xms1024m -Xmx1024m"

참조 링크


1
왜 1 : 1 또는 1 : 1.5 비율로 유지해야하는지 아십니까?
ernesto

7

개발을 위해 기본적으로 JVM은 다른 성능 관련 기능을 위해 작은 크기와 작은 구성을 사용합니다. 그러나 생산을 위해 조정할 수 있습니다 (예 : Application Server 특정 구성이 존재할 수 있음)-> (요청을 충족시킬 메모리가 충분하지 않고 힙이 이미 최대 크기에 도달하면 OutOfMemoryError가 발생합니다)

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size
-Xss<size>        set java thread stack size

-XX:ParallelGCThreads=8
-XX:+CMSClassUnloadingEnabled
-XX:InitiatingHeapOccupancyPercent=70
-XX:+UnlockDiagnosticVMOptions
-XX:+UseConcMarkSweepGC
-Xms512m
-Xmx8192m
-XX:MaxPermSize=256m (in java 8 optional)

예를 들면 다음과 같습니다. Linux 플랫폼에서 프로덕션 모드 기본 설정.

이 방법으로 서버를 다운로드하고 구성한 후 http://www.ehowstuff.com/how-to-install-and-setup-apache-tomcat-8-on-centos-7-1-rhel-7/

1. / opt / tomcat / bin / 폴더에 setenv.sh 파일을 만듭니다

   touch /opt/tomcat/bin/setenv.sh

2.이 모드를 열어서 선호 모드를 설정하십시오.

nano  /opt/tomcat/bin/setenv.sh 

export CATALINA_OPTS="$CATALINA_OPTS -XX:ParallelGCThreads=8"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+CMSClassUnloadingEnabled"
export CATALINA_OPTS="$CATALINA_OPTS -XX:InitiatingHeapOccupancyPercent=70"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UnlockDiagnosticVMOptions"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseConcMarkSweepGC"
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m"
export CATALINA_OPTS="$CATALINA_OPTS -Xmx8192m"
export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxMetaspaceSize=256M"

삼.service tomcat restart

JVM은 힙보다 더 많은 메모리를 사용합니다. 예를 들어 Java 메소드, 스레드 스택 및 기본 핸들은 JVM 내부 데이터 구조뿐만 아니라 힙과 별도로 메모리에 할당됩니다.


7

Java 힙 크기와 동일한 문제에 직면했습니다.

java 5 (1.5)를 사용하는 경우 두 가지 해결책이 있습니다.

  1. jdk1.6을 설치하고 eclipse의 환경 설정으로 이동하여 설치 한 jav1 1.6의 jre 경로를 설정하십시오.

  2. VM 인수를 확인하고 그것이 무엇이든 그대로 두십시오. VM 인수에 존재하는 모든 인수 중 하나를 -Xms512m -Xmx512m -XX : MaxPermSize = ... m (192m)으로 한 줄 아래에 추가하십시오.

나는 그것이 효과가 있다고 생각합니다 ...


7

런타임시 메모리 사용량을 모니터링해야하는 경우 java.lang.management패키지는 MBeansVM의 메모리 풀 (예 : 에덴 공간, 테너 링 생성 등) 및 가비지 콜렉션 동작을 모니터링하는 데 사용할 수있는 오퍼 를 제공 합니다.

이러한 MBean에 의해보고 된 여유 힙 공간은 GC 동작에 따라 다르며, 특히 응용 프로그램이 나중에 GC가되는 많은 오브젝트를 생성하는 경우에 그러합니다. 하나의 가능한 접근 방식은 각 전체 GC 후에 사용 가능한 힙 공간을 모니터하는 것입니다. 이는 오브젝트를 유지함으로써 메모리 확보에 대한 결정을 내리는 데 사용할 수 있습니다.

궁극적으로 최선의 방법은 성능을 유지하면서 가능한 한 메모리 보존을 제한하는 것입니다. 이전 의견에서 언급했듯이 메모리는 항상 제한되어 있지만 앱에는 메모리 소모를 처리하는 전략이 있어야합니다.


5

배치 상황에서이를 필요로하는 경우, Java WebStart (네트워크상의 버전이 아닌 "온 디스크"버전과 함께-Java 6u10 이상에서 가능)를 사용하여 JVM에 대한 다양한 인수를 교차로 지정할 수 있습니다 플랫폼 방식.

그렇지 않으면 필요한 인수를 설정하는 운영 체제 별 실행기가 필요합니다.


Java WebStart가 단계적으로 중단되고 있습니다. 적절한 교체 방법을 아직 모릅니다.
Thorbjørn Ravn Andersen

1

이 문제가 Wildfly 8 및 JDK1.8에서 발생하는 경우 PermGen 설정 대신 MaxMetaSpace 설정을 지정해야합니다.

예를 들어 wildfly의 setenv.sh 파일에 아래 구성을 추가해야합니다. JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceSize=256M"

자세한 내용은 Wildfly Heap Issue 를 확인하십시오.


1

넷빈과 관련하여 문제를 해결하기 위해 최대 힙 크기를 설정할 수 있습니다.

'실행'으로 이동 한 다음-> '프로젝트 구성 설정'-> '사용자 정의'-> 팝업 창의 '실행'-> 'VM 옵션'-> '-Xms2048m -Xmx2048m'을 입력하십시오. .


1

객체에 대한 참조를 계속 할당하고 유지하면 보유한 메모리 양이 채워집니다.

하나의 옵션은 탭을 전환 할 때 투명한 파일 닫기 및 열기를 수행하는 것입니다 (파일에 대한 포인터 만 유지하고 사용자가 탭을 전환 할 때 모든 객체를 닫고 정리하면 파일 변경이 느려집니다) ...하지만 ...), 메모리에 3-4 개의 파일 만 보관하십시오.

사용자가 파일을 열고로드하고 OutOfMemoryError를 가로 챌 때 (파일을 열 수 없으므로) 해당 파일을 닫고 오브젝트를 정리 한 후 사용하지 말아야한다는 경고 메시지를 표시해야합니다. 파일.

가상 메모리를 동적으로 확장하려는 아이디어는 문제를 해결하지 못합니다. 시스템은 리소스가 제한되어 있으므로 메모리 문제를주의해서 처리해야합니다 (또는 최소한주의해야합니다).

메모리 누수로 본 몇 가지 힌트는 다음과 같습니다.

-> 컬렉션에 무언가를 넣은 후에도 잊어 버린다면 여전히 강한 참조가 있으므로 컬렉션을 무효화하거나 청소하거나 컬렉션을 사용하여 수행하십시오. 메모리 누수가 찾기 어렵습니다.

-> 어쩌면 약한 참조 (weakhashmap ...)가있는 컬렉션을 사용하면 메모리 문제에 도움이 될 수 있지만 조심 해야합니다. 찾는 객체가 수집되었음을 알 수 있습니다.

-> 내가 찾은 또 다른 아이디어는 가장 적게 사용되고 투명하게로드 된 데이터베이스 객체에 저장된 영구 컬렉션을 개발하는 것입니다. 이것은 아마도 가장 좋은 방법 일 것입니다 ...


0

다른 모든 것이 실패하면 최대 힙 크기를 늘리는 것 외에도 스왑 크기를 늘리십시오. Linux의 경우 현재 https://linuxize.com/post/create-a-linux-swap-file/ 에서 관련 지침을 찾을 수 있습니다 .

예를 들어 임베디드 플랫폼에서 큰 것을 컴파일하는 경우 도움이 될 수 있습니다.

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