[자바] 메모리 관리(쓰레기 수집가)

박지운·2023년 8월 20일
0

자바 꽉 자바

목록 보기
11/12

코테를 c++로 하면서 메모리 관련 버그가 나고, malloc과 free를 쓸 때마다 자바의 메모리 관리에서의 편리함을 느낀다.
자바는 C++과 달리 메모리를 직접 비우지 않고 가비지 컬렉션을 사용하는데 어떤 방식으로 사용되는지 알아보자.

Microsoft 버그의 70%는 메모리 관련 버그이다.

가비지 콜렉션이란?

프로그램 개발시 유효하지 않은 메모리인 가비지가 발생한다.


public class Example {
    public static void main(String[] args) {
        String str1 = new String("junsik");
        String str2 = new String("bex");

        str1 = str2; // str1은 이제 "bex"를 가리킨다.
    }
}

위 예시에서 "junsik"에 대한 참조가 없어져 가비지가 된다.
java는 가비지 컬렉터(GC)가 주기적으로 검사해 메모리를 청소해준다.


GC의 청소 방식

Mark And Sweep

가비지 컬렉션이 동작하는 기초적인 청소 과정이다.

원리는 대상 객체를 식별, 제거하며 이후 파편화된 메모리를 앞에서부터 채워나가는 작업을 수행한다. 위에 봤듯이 참조되지 않는 대상을 청소해야하는데 어떻게 알 수 있을까?
바로 그래프를 이용한다.

  • Mark(식별) : 먼저 메모리의 Root로부터 그래프 순회를 통해 연결된 객체를 가각 찾아내어 참조하는 객체를 마킹한다.
  • Sweep(제거) : 참조되지 않은 객체(Unreachable)들을 Heap에서 제거한다. 파란색 객체들을 제거하는 것이다.
  • Compact : Sweep 이후 분산된 객체들을 Heap 시작주소로 모아 메모리가 할당된 부분과 아닌 부분으로 압축한다.

동작 과정

java의 heap

  • new 키워드로 생성된 객체와 배열이 생성되는 영역이다.
  • 주기적으로 GC가 제거하는 영역이다.

Young Generation 영역은 객체가 생성되고 얼마 안됐을 때 저장되는 공간이다.힙에 생성 시 최초 Eden 영역에 할당된다. 이후 어느 정도 데이터가 쌓이게 되면 참조 정도에 따라 survivor의 빈 공간으로 이동되거나 회수된다.
위 Old로 이동되거나 회수되는 것을 Minor GC 라고 한다. Old영역은 Tenured Generation이라고도 불리고 종신직, 임기의 뜻을 갖고 있다.

Old 영역에 할당된 메모리가 허용치를 넘으면 Old에 모든 객체를 검사하여 참조되지 않는 객체들을 한꺼번에 삭제하는 GC가 실행된다. 이때 GC실행 스레드를 제외한 모든 스레드는 작업을 멈추므로 이를 Stop-the-World가 발생한다고 하고 Old영역의 메모리를 회수하는 CG를 Major CG라고 한다.

알고리즘

Heap의 사이즈가 자바의 발전에 맞춰 점차 커지면서 최적화를 위해 GC 알고리즘이 개발되었다.
상황에 따라 적용이 가능하다.

Serial GC

  • 서버의 CPU 코어가 1개일 때 사용하는 단순한 GC
  • GC 스레드가 1개이므로 stop-the-world가 가장 길다.
  • CPU 코어가 1개인 경우가 아니라면 사용하지 말자!

Parallel GC

  • Java8의 디폴트 GC이다.
  • Serial GC와 기본적인 개념은 같지만, Youn 영역의 Minor GC를 멀티 스레드로 수행한다.

Parallel old GC

  • 위 Parallel GC에서 Old영역도 멀티 스레드로 GC를 수행하도록 한 것이다.

CMS GC(Concuurent Mark Sweep)

  • 어플리케이션 스레드와 GC 스레드가 동시 실행되는 것이다.
  • GC과정이 매우 복잡하고 CPU, 메모리 파편화 등 여러 문제로 Java 14에서는 사용이 중지되었다.

G1 GC

  • CMS를 대체하기 위해 나왔다.
  • Heap이 너무 작을경우 미사용 권장된다.
  • G1 gc는 young/Old 영역을 나누지 않고 Region이라는 개념을 도입하여 사용한다. 힙 내부 영역을 동적으로 부여해 GC빈도를 줄인다.

Z GC

  • Java15에 릴리즈
  • 대량의 메모리를 처리하기 위해 나왔다.
  • ZPage영역을 사용, 힙 크기가 증가하더라도 'stop-the-world'의 시간이 절대 10ms를 넘지 않는다고한다.

GC 단점

  • 개발자는 메모리가 언제 해제되는지 정확히 알 수 없다.
  • GC 동작 중에 다른동작을 멈추므로 오버헤드가 발생한다.

GC가 c++에 비해 편리할 수 있지만 오버헤드가 일어날 수 있다. GC가 있다하더라도 개발자에게 메모리 관리는 항상 신경써야하는 문제인 것 같다...!!


티스토리(망나니개발자)
벨로그(YoungHo-Cha)

profile
앞길막막 전과생

0개의 댓글