[JAVA]GC

JHJeong·2024년 3월 15일
0

Garbage Collection

메모리 관리 기법 중 하나로, 프로그래머가 동적으로 할당한 메모리 영역 중에서 더 이상 쓰이지 않는 영역을 자동으로 찾아내어 해제하는 기능이다.

자바에서는 JVM의 Heap 영역에서 사용하지 않는 객체를 삭제하는 프로세스를 말한다.

힙영역에는 Object 타입의 데이터( String, List와 같은 데이터들)가 할당되어 지는데, 이 중에서 참조하지 않는 객체들을 정리 하게되는데, 어떻게 참조하지 않는 객체인지 구분하는 것일까?

GC는 이러한 참조하지 않는 객체를 구분하기 위해서 애플리케이션의 Root에서부터 시작해서 참조 체인을 따라가면서 도달할 수 있는 객체인지를 판단해서 Reachable(도달 가능한)객체와 Unreachable(도달 불가능한)객체를 구분한다.

  • 루트 객체(Roots) : Stack 영역의 데이터들, Method영역의 Static 데이터들, JNI에 의해 생성된 객체들에서 참조하지 않는 객체들을 찾아서 판단한다.
  • Reachability(도달 가능성) : 가비지 컬렉터는 루트 객체들에서부터 시작해서 도달 가능한 객체들을 찾는다. 즉, 어떤 방법으로든 루트 객체에서 참조되는 객체들은 도달 가능한 객체로 간주됩니다.
  • Reachable Objects(도달 가능한 객체들) : 도달 가능한 객체들은 다른 객체에 의해 직접 또는 간접적으로 참조된다. 즉, 어떤 경로를 통해도 루트 객체에 도달할 수 있는 객체들이다.
  • Unreachable Objects(도달 불가능한 객체들) : 도달 가능한 객체가 아닌 객체들은 도달 불가능한 객체로 간주된다. 즉, 어떤 방법으로도 도달할 수 없는 객체들이다. 이러한 객체들이 가비지 컬렉션의 제거 대상이 된다.

Mark And Sweep

그리고 이러한 Unreachable 객체들을 정리하기 위한 알고리즘이 있는데 JAVA에서는 기본적으로 Mark And Sweep 이라는 알고리즘으로 동작한다. 이 알고리즘은 크게 2단계로 이루어지게된다.

1단계(Mark) : 가비지 컬렉션은 루트 객체로부터 모든 변수를 스캔하면서 각각 어떤 객체를 참조하고 있는지 찾아서 마킹한다.
2단계(Sweep) : 1단계에서 마킹하지 못한 Unreachable 객체들을 Heap에서 제거한다.
추가적으로 Compact라고 하는 과정이 있다.( Sweep 이후에 분산된 객체들을 Heap의 시작 주소로 모아서 메모리가 할당된 부분과 할당하지 않은 부분으로 나누는 과정이고, 메모리 단편화를 방지하기 위해서 추가하는 과정이다. )

이렇게 한 사이클에서 Mark And Sweep, 어쩔때는 Compact까지 돌게 되면서 Heap을 정리하게 된다.

Heap의 구조

  • Young Generation : 새로운 객체들이 할당되는 영역이고, 대부분의 객체는 여기서 빠르게 소멸되므로 적은 수의 GC가 발생한다. ( Eden, Survivor0, Survivor1 영역으로 존재 )
  • Old Generation : Young Generation에서 오랫동안 살아남은 객체들이 존재하는 영역이다. 이 영역은 상대적으로 가비지컬렉션이 더 늦게 발생하고, 메모리를 더 오래 유지하는 객체들을 위해서 사용되는 영역이다.

GC의 작동순서

  1. 새로운 객체들이 에덴영역에 할당된다.
  2. 에덴 영역이 꽉 차게되면 Minor GC가 발생한다. 이때 Reachable한 객체들을 마크하고, 마크되지 않은 Unreachable 객체들을 Heap에서 제거한다.
  3. 그 후 GC에서 살아남은 객체들을 Survivor영역으로 이동한다. 그리고 Age를 1씩 더해준다. (이때 Survivor영역은 0과 1 둘 중에 하나만 사용하게되는데, 만약 0이 사용중이면 1을 비워야한다. )
  4. 그 뒤 새로운 객체들이 에덴영역에 할당되고, 다시 2번 작업 후에 살아남은 객체들은 사용하지 않는 Survivor 영역으로 이동한다.
  5. 또한 특정 임계점의 Age가 되면 Old Generation 으로 이동하고, 이러한 오래된 객체들이 많으면 Major GC가 일어난다.
  6. Major GC 또한 Minor GC 처럼 Mark And Sweep 과정을 통해서 Unreachable 객체들을 제거한다.

Minor GC는 주로 멈춤없이 또는 매우 짧은 일시 중지 시간으로 처리되는 반면에, Major GC는 Minor GC보다 더 오랫동안 일시 중지될 수 있다. 때문에 Major GC가 발생하는 동안 애플리케이션 성능에 영향을 줄 수 있다.

Stop-The-world

가비지컬렉션 중 일시 중지되는 현상을 의미한다.
가비지컬렉션이 실행되는 동안 JVM이 애플리케이션의 실행을 일시 중지하고 가비지 컬렉션을 수행한다. 이 일시 중지는 주로 Major GC가 발생할 때 나타나며, 애플리케이션의 응답시간에 영향을 줄 수 있다. 물론 Minor GC에서도 Stop-the-world가 발생하긴 하지만 매우 짧은 시간이기 때문에 성능에 영향을 크게 주진 못한다.
이러한 Stop-the-world가 발생하는 동안 JVM은 모든 애플리케이션 스레드를 일시 중지시키고, 가비지컬렉션을 위해서 전용 스레드를 실행한다. 이 과정에서 애플리케이션은 일시 중지 되므로 stop-the-world의 시간을 최소하는게 중요하다. JAVA의 GC튜닝은 이러한 Stop-the-world의 시간을 최적화하는 것을 포함한다.

JAVA에서의 GC 종류

  1. Serial GC
  • 단일 스레드로 가비지 컬렉션을 처리한다.
  • 주로 단일 프로세서 시스템이나, 작은 규모의 애플리케이션에 적합하다.
  • 다른 GC에 비해 stop-the-world시간이 길다.
  • mark-compact 과정이 들어간다.
  • '-XX: +UseSerialGC' 옵션을 사용하여 활성화 할 수 있다.
  1. Parallel GC
  • Young Generation의 GC를 멀티스레드로 수행하여 가비지 컬렉션을 병렬로 처리합니다.
  • 대규모 멀티코어 시스템에서 빠른 가비지 컬렉션을 제공한다.
  • 주로 서버 애플리케이션에 사용된다.
  • Serial GC에 비해 stop-the-world 시간이 감소한다.
  • JAVA 8의 default GC
  • '-XX:+UseParallelGC' 옵션을 사용하여 활성화할 수 있다.
  1. CMS(Concurrent Mark-Sweep) GC
  • 마크-스위프트 단계를 병행(concurrent)으로 실행하여 일시 중지 시간을 최소화한다.
  • 반응성이 중요한 애플리케이션에서 사용된다.
  • stop-the-world을 최소화하기 위해 옵션을 조정할 수 있다.
  • compact과정이 없다.(그래서 메모리 단편화문제가 좀 아쉽다.)
  • reachable한 객체를 한번에 찾지 않고, 순차적으로 찾는게 특징이다.
  • '-XX:+UseConcMarkSweepGC' 옵션을 사용하여 활성화할 수 있다.

4.G1(Garbage-First) GC

  • CMS GC를 개선
  • 힙을 논리적인 영역(Region)으로 나누고 각 영역을 병렬로 처리하여 가비지 컬렉션을 수행한다.
  • 큰 힙 크기와 대규모 애플리케이션에서 효율적이다.
  • Java 9이상의 default GC
  • '-XX:+UseG1GC' 옵션을 사용하여 활성화할 수 있다.
profile
이것저것하고 싶은 개발자

0개의 댓글