[Java] Garbage Collector

CS 스터디를 하면서 공부했던 GC에 대해 정리해보았다.

목차

1. 프로그램 메모리 관리 기법

2. Garbage Collector

3. Java Garbage Collector


프로그램 메모리 관리 기법

  • C언어는 개발자가 직접 메모리를 관리해야 한다. (malloc(), free())
    • 메모리를 개발자가 직접 관리해야 하다보니 개발에 어려움이 많았음
    • 이러한 개발자의 고충을 줄여준 것이 GC(Garbage Collector)
    • GC가 알아서 사용하지 않는 메모리를 해제해줌

Garbage Collector

  • 정의
    • 동적 할당된 메모리 영역 가운데 더 이상 사용할 수 없게 된 영역을 탐지하여 자동으로 해제해주는 기법
  • 장점
    • 메모리 누수 방지
    • 해제된 메모리에 접근 방지
    • 해제된 메모리를 다시 해제하는 행동 방지
  • 단점
    • GC 작업 자체는 프로그램 실행의 오버헤드가 됨
    • 개발자는 메모리가 해제되는 타이밍을 알기 힘듬

GC 알고리즘

  • Reference Counting
    • GC의 초기 알고리즘
    • Garbage를 발견하는 것에 초점이 맞춰져 있음
    • 어느 한 메모리가 다른 메모리를 얼마나 많이 참조하는지 횟수를 세어서 메모리 접근 가능과 불가능을 나누는 방식
    • 객체가 참조되거나 역참조될 때마다 GC가 작동함
    • 순환 참조 문제를 해결하지 못하는 한계점을 갖고 있음

image


  • Mark And Sweep
    • Reference Counting 방식의 순환참조 문제를 해결한 알고리즘
    • root에서부터 해당 객체에 접근 가능한지를 해제의 기준으로 삼음
    • Mark단계와 Sweep단계로 나뉨
    • 의도적으로 GC를 실행시켜야 함
    • 어플리케이션 실행과 GC 실행이 병행됨

MarkAndSweep1

초기에 위와같은 메모리 구조가 있고 GC가 실행되면 Mark단계가 실행되어 root에서부터 접근할 수 있는 모든 객체를 확인함


MarkAndSweep2

Mark단계를 통해 접근할 수 있는 객체를 Reachable이라하고 연결이 끊어진 객체를 UnReachable이라고 부른다. Mark단계가 끝나면 Sweep단계로 넘어가서 UnReachable 객체들을 해제함


MarkAndSweep3

Sweep단계가 끝나고 메모리 파편화 현상을 막기 위해 Compation이라는 과정을 거치기도 하는데 이 과정을 거치면 Reachable 객체 메모리 주소가 응집 됨


MarkAndSweep4


Java Garbage Collector

  • Java의 GC는 Mark And Sweep 알고리즘으로 동작함
  • GC를 실행하기 위해선 어플리케이션의 실행을 멈춰야 하는데 이를 가리켜서 stop-the-world라고 함
    • GC튜닝이란 stop-the-world의 시간을 줄이는 것

JVM 구조

image

  • Class Loader
    • 바이트 코드를 읽고 클래스 정보를 메모리의 Heap/Method Area에 저장함
  • Runtime Data Area
    • 실행중인 프로그램의 정보가 올라가 있는 메모리 영역
  • Excution Engine
    • 바이트코드를 어셈블러 같은 네이티브코드로 변환시켜줌

JVM 메모리 구조

image

  • 전체쓰레드 공유
    • Method Area
      • 클래스의 필드, 메소드 정보, static 변수 등의 정보를 저장해둠
    • Heap
      • 클래스의 인스턴스와 배열이 할당되는 영역
      • 할당된 객체는 직접 해제가 불가능하며 오로지 GC에 의해 해제됨
  • 쓰레드별 데이터 영역
    • PC Register
      • 쓰레드가 현재 실행할 스택 프레임의 주소를 저장
    • Stack
      • 메서드 호출을 스택 프레임이라는 블록으로 쌓으며 로컬 변수, 중간 연산 결과들이 저장되는 영역
    • Native Method Stack
      • C나 C++ 등의 Low Level 코드를 실행하는 스택(JNI 참조)
  • GC의 root space는 Stack, Native Method Stack, Method Area

image

  • Young Generation
    • 생성된지 얼마 안된 객체들이 저장되는 장소 대부분의 객체가 이 영역에서 생성되었다가 Minor GC를 통해 사용되지 않는 객체가 제거됨
    • eden
      • 새롭게 생성된 객체들이 할당되는 영역
    • Survival0
      • eden에서 Minor GC로부터 살아남은 객체들이 S1과 번갈아가며 존재하는 영역
    • Survival1
      • eden에서 Minor GC로부터 살아남은 객체들이 S0과 번갈아가며 존재하는 영역
  • Old Generation
    • 생성된지 오래된 객체들이 저장되는 장소, Young 영역에서 살아남은 객체가 이곳으로 옮겨지고 Major GC를 통해 사용되지 않는 객체가 제거됨
  • Permanent Generation
    • 프로그램 코드가 올라가는 부분, Code가 모두 로딩되고 나면 거의 일정한 수치를 유지함

Minor GC, Major GC

  • Young Generation에서 사용하는 GC를 Minor GC라고 함
    • Copying garbage 알고리즘으로 동작
      • root에서 그래프순회 객체들을 mark하고 그대로 이동할 메모리 영역에 붙여넣는 방식

image

image

  • Old Generation에서 사용하는 GC를 Major GC라고 함
    • Mark ANd Sweep 알고리즘으로 동작

GC의 동작

image

eden영역이 꽉 차면 Minor GC가 동작함

image

살아남은 객체는 S0로 이동하고 age-bit가 상승함

image

eden영역이 또 꽉 차면 Minor GC가 동작함

image

이전엔 S0에 이동했으므로 이번에 살아남은 객체들은 모두 S1영역으로 이동하고 age-bit가 상승함(S0에 살아남아있던 객체3개와 이번에 eden에서 살아남은 객체 2개)

이후에도 위와같이 S0과 S1을 번갈아가며 객체를 이동시키다가 age-bit가 특정 숫자이상 올라가면 오래도록 참조될 객체라고 판단하여 Old영역으로 객체를 이동시켜줌, 이 과정을 Promotion이라고 함 (Java8에서는 Parallel GC기준 age-bit가 15가 되면 이동)

image

Old영역도 가득차게 되면 Major GC가 발생하며 Mark And Sweep 방식으로 필요없는 메모리를 비워주게 됨 (Major GC가 Minor GC보다 오래걸림)

영역을 나눠서 GC를 하는 이유

  • 대부분의 객체들은 금방 사라짐
  • GC는 자체가 오버헤드
    • 따라서 특정 메모리영역만 탐색해서 해제하면 더 효율적

image


참고

  • https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=kbh3983&logNo=220967456151
  • https://hongsii.github.io/2018/12/20/jvm-memory-structure/
  • https://rebelsky.cs.grinnell.edu/Courses/CS302/99S/Presentations/GC/
  • https://steady-coding.tistory.com/305
  • https://www.youtube.com/watch?v=FMUpVA0Vvjw
  • https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/generations.html

태그: ,

카테고리:

업데이트:

댓글남기기