Programming/Java

JAVA 메모리 영역과 OOM에 대하여

d-e-v-j 2024. 8. 28. 02:00
반응형

JAVA 가 실행되는 동안에 JVM(Java Virtual Machine)은 메모리를 여러 영역으로 나누어 사용한다. 각 메모리 영역은 특정한 목적을 위해 사용되며, 이러한 메모리 영역에서 메모리가 부족할 때 OutOfMemoryError(OOM) 예외가 발생할 수 있다. 메모리 영역과 OOM에 대하여 알아보자


JAVA 메모리 영역

Java 메모리 영역은 크게 다섯 가지로 나뉜다.

 

  1. Heap:
    • 정의: Heap 영역은 Java 객체와 배열이 동적으로 할당되는 메모리 공간. 대부분의 Java 애플리케이션 데이터는 이 영역에 저장
    • 특징:
      • JVM은 힙을 크게 두 가지 영역으로 나뉜다: Young Generation(새로 생성된 객체가 저장되는 공간)과 Old Generation(Young Generation에서 오래 살아남아 GC에서 제거되지 않은 객체가 저장되는 공간).
      • 가비지 컬렉션(Garbage Collection)이라는 자동 메모리 관리 메커니즘이 적용되어, 더 이상 참조되지 않는 객체를 정리하여 메모리 누수를 방지
    • OOM 종류: java.lang.OutOfMemoryError: Java heap space
      • 원인: 힙 공간이 부족하여 새로운 객체를 생성할 수 없는 경우 발생
      • 예시: 대량의 데이터 구조를 메모리에 올리거나, 큰 배열을 할당할 때 발생할 수 있다.
  2. Stack:
    • 정의: Stack 영역은 각 스레드마다 생성되는 메모리 공간으로, 스레드가 메서드를 호출할 때마다 메서드 호출 스택이 여기에 쌓인다.
    • 특징:
      • 각 메서드 호출마다 스택 프레임(Stack Frame)이 생성되어 메서드의 로컬 변수, 매개변수, 리턴 주소 등이 저장
      • 메서드 호출이 끝나면 해당 스택 프레임은 스택에서 제거
    • OOM 종류: java.lang.StackOverflowError
      • 원인: 스택 메모리 한도를 초과하는 재귀 호출 또는 무한 루프에서 발생
      • 예시: 무한 재귀 함수 호출 또는 너무 깊은 재귀 호출이 이루어졌을 때 발생할 수 있다.
  3. Metaspace (JDK 8 이상):
    • 정의: Metaspace는 JVM이 클래스 메타데이터를 저장하는 메모리 영역. JDK 8 이전에는 PermGen(Permanent Generation)이라는 영역이 사용되었다.
    • 특징:
      • 클래스 메타데이터(예: 클래스 구조, 메서드 정보, 상수 풀 등)가 저장
      • JDK 8 이전의 PermGen과 달리 Metaspace는 기본적으로 운영 체제의 네이티브 메모리를 사용하며, 크기가 제한되지 않는다.
    • OOM 종류: java.lang.OutOfMemoryError: Metaspace
      • 원인: Metaspace 영역의 메모리가 부족할 때 발생
      • 예시: 너무 많은 클래스를 동적으로 로드하거나, 클래스 로더가 메모리에서 클래스를 해제하지 않는 경우 발생할 수 있다.
  4. Code Cache:
    • 정의: Code Cache는 JVM의 Just-In-Time (JIT) 컴파일러가 생성한 네이티브 코드가 저장되는 메모리 영역
    • 특징:
      • 자주 실행되는 Java 바이트코드를 네이티브 코드로 컴파일하여 애플리케이션의 성능을 향상
    • OOM 종류: java.lang.OutOfMemoryError: Code Cache
      • 원인: JIT 컴파일러가 생성한 네이티브 코드가 Code Cache의 용량을 초과할 때 발생
      • 예시: 애플리케이션에 많은 메서드가 JIT 컴파일되고, Code Cache의 크기를 초과할 경우 발생할 수 있다.
  5. Thread:
    • 정의: Java 애플리케이션에서 각 스레드는 운영 체제의 네이티브 스레드와 매핑되며, 이에 따라 각 스레드가 필요한 스택 메모리와 네이티브 리소스를 할당
    • OOM 종류: java.lang.OutOfMemoryError: Unable to create new native thread
      • 원인: 시스템의 메모리나 프로세스 한계로 인해 새로운 스레드를 생성할 수 없는 경우 발생
      • 예시: 너무 많은 스레드를 생성하려 할 때나, 시스템의 프로세스 제한에 도달했을 때 발생할 수 있다.

OutOfMemoryError(OOM)의 종류 요약

  1. Java heap space: 힙 영역에서 메모리가 부족할 때 발생.
  2. StackOverflowError: 스택 메모리의 한도를 초과하는 경우 발생.
  3. Metaspace: 메타스페이스 영역에서 메모리가 부족할 때 발생 (JDK 8 이상).
  4. Code Cache: JIT 컴파일러의 네이티브 코드가 저장되는 Code Cache에서 메모리가 부족할 때 발생.
  5. Unable to create new native thread: 새로운 스레드를 생성할 수 없을 때 발생.

OOM 예외 해결 방법

  1. Java heap space:
    • 힙 크기 조정: JVM 옵션을 사용하여 힙 크기(-Xmx)를 늘리거나 줄인다다.
    • 메모리 사용량 분석: 애플리케이션의 메모리 사용을 분석하고, 메모리 누수(leak)를 검사한다.
    • 코드 최적화: 메모리를 많이 사용하는 코드를 최적화하여 사용량을 줄인다.
  2. StackOverflowError:
    • 재귀 호출 제한: 재귀 호출을 사용할 때는 적절한 종료 조건을 설정하여 무한 루프를 방지
    • 스택 크기 조정: JVM 옵션을 사용하여 스택 크기(-Xss)를 늘린다.
  3. Metaspace:
    • Metaspace 크기 조정: JVM 옵션을 사용하여 메타스페이스 크기(-XX:MaxMetaspaceSize)를 늘린다
    • 클래스 로더 문제 해결: 불필요한 클래스 로더를 정리하여 메타스페이스 사용량을 줄인다
  4. Code Cache:
    • Code Cache 크기 조정: JVM 옵션을 사용하여 Code Cache 크기(-XX:ReservedCodeCacheSize)를 늘린다
  5. Unable to create new native thread:
    • 스레드 수 제한: 애플리케이션이 생성하는 스레드 수를 제한
    • 시스템 자원 확인: 운영 체제의 자원 사용을 점검하고, 프로세스 및 스레드 제한을 조정

OOM 오류는 일반적으로 메모리 리소스 관리와 관련된 문제로 발생하므로, JVM의 메모리 설정을 적절히 조정하고 애플리케이션 코드를 최적화하여 메모리 사용을 효율적으로 관리하는 것이 중요하다.

 

728x90
반응형
LIST