Java | 메모리 단편화와 GC

Lumpen·2025년 4월 9일
0

Java

목록 보기
14/40

단편화

메모리 단편화는 컴퓨터 메모리(RAM)를 효율적으로 사용하지 못하게 되는 현상
가용 공간의 크기는 충분함에도 메모리를 사용하고 있는 데이터가 산발되어 있어
연속된 메모리 블록을 할당할 수 없는 상태를 말한다

내부 단편화

  • 메모리가 할당된 후 사용되지 않는 공간이 할당 블록 내에서 낭비되는 현상
  • 메모리를 고정된 크기의 블록 단위로 할당하기 떄문에 요청한 크기보다 더 큰 메모리 블록이 할당될 수 있고, 남은 부분에 대해 사용되지 않아 낭비된다

외부 단편화

  • 메모리 블록이 할당 및 해제되면서 연속적이지 않은 빈 공간이 여기저기 흩어져 생기는 현상
  • 메모리 공간은 충분하지만, 연속된 공간의 할당이 불가능한 경우

윈도우OS 에서 디스크 조각 모음을 하는 이유와 외부 단편화가 비슷한 것 같다
보조 기억 장치와 주 기억 장치의 차이가 있지만

메모리 단편화 발생 원인

  • 프로그램의 동적 메모리 할당 및 해제 과정에서 다양한 크기의 메모리 블록이 생성, 소멸되면서 발생
  • 메모리 할당 알고리즘의 비효율도 단편화의 원인이 될 수 있다

메모리 단편화의 문제점

  • 메모리 낭비: 가용한 메모리 공간이 줄어 시스템 성능 저하를 유발
  • 프로그램 실행 속도 저하: 필요한 메모리 블록을 찾기 위해 더 많은 시간이 소요될 수 있다
  • 시스템 불안정성: 심각한 경우 시스템 충돌 발생

메모리 단편화를 고려한 프로그래밍

메모리 사용 공간 선택하는 것을 개발자가 직접 관여할 수는 없지만
효율적으로 관리할 수는 있다
자바 JVM 의 가비지 컬렉션의 성능이 매우 우수하지만
언제든 메모리 누수와 단편화가 일어날 수 있다

아래와 같은 방법으로 메모리를 효율적으로 간리할 수 있다

  • 객체 풀링: 자주 생성되고 소멸되는 객체의 메모리 공간을 미리 할당, 재사용하여 메모리 할당 및 해제 횟수를 줄인다 (메모리 사용량을 고려해 적절한 크기만 사용해야 함)
  • 객체 생명 주기 관리: 더 이상 사용하지 않는 객체에 대해 null 로 초기화하여 가비지 컬렉션의 대상이 되지 않도록 하고, 생명 주기를 적절히 관리한다
  • 큰 객체 할당 최소화: 꼭 필요하지 않은 경우 큰 객체를 메모리에 계속 두거나, 자주 할당 및 해제를 하지 않도록 한다
  • 문자열 처리 최적화: 문자열은 불변 객체이므로 연산이 많아지면 많은 임시 객체가 생성되므로 주의해야 한다 (StringBuilder 또는 StringBuffer 를 사용하여 문자열 연산을 최소화)

객체 풀링

객체 풀링은 큐(pool)를 구현하여 일정 크기의 메모리를 미리 초기화하여 확보한 후
풀 내에서 하나씩 작업을 처리한다
지정된 메모리 공간에서 반복 작업을 하게 하여 메모리 할당과 해제를 한 번만 하도록 구현하는 방법
메모리를 미리 할당하기 위해 static 을 사용한다

객체 풀링 주의사항

  • 객체 풀은 thread-safe 하지 않으므로 멀티 스레트 환경에서는 동기화 처리를 해야 함
  • 풀의 크기를 적절히 설정해야 함 (너무 작으면 풀을 사용하지 못하는 경우 발생, 너무 크면 메모리 낭비)
  • 객체를 풀에 반환할 때 객체를 초기화하여 다음 사용에 문제가 없도록

이러한 방법은 메모리를 효율적으로 처리할 뿐만 아니라
메모리 단편화 등을 줄일 수 있고, 객체 생성 및 소멸에 대한 오버헤드를 줄일 수 있다
또한 가비지 컬렉션의 일을 줄여주고, 그로인한 작업 비용과 오버헤드 또한 줄일 수 있다

가비지 컬렉션

가비지 컬렉션 또한 JVM 에서 동작하는 작업이기 떄문에
가비지 컬렉션의 동작이 프로그램 전체의 성능에 영향을 미칠 수 있다
일부 알고리즘은 가비지 컬렉션을 수행하는 동안 애플리케이션을 일시 중지하는데
이를 stop-the-world 라고 표현한다

때문에 가비지 컬렉션의 일을 줄여주는 편이 좋다

profile
떠돌이 생활을 하는. 실업자, 부랑 생활을 하는

0개의 댓글