JVM과 GC

뾰족머리삼돌이·2023년 12월 19일
0

JAVA

목록 보기
3/8

JVM ( 자바 가상머신 )

모든 소스코드들은 실행하기 전에 컴파일이나 인터프리트 과정을 거쳐야한다

  • 컴파일 ⇒ 한번에 다 읽어서 실행가능한 상태로 만들고 실행 ( C/C++ )
  • 인터프리트 ⇒ 한줄씩 읽으면서 실행하기 ( JavaScipt )

JAVA에서는 프로그램을 실행하는데 있어서 두 가지를 모두 사용한다

  1. 자바 Compiler가 바이너리 형태의 ByteCode를 생성
  2. 자바 Interpreter가 플랫폼에 맞게 ByteCode를 한줄씩 실행

💡 ByteCode : JVM 전용 기계어
JVM은 해당 이진 ByteCode를 동작하는 플랫폼에 맞는 기계어로 변환한다

JVM은 기존 프로세스위에서 동작하는 가상의 기계역할을 하며 Java API와 함께 Java 개발을 할 수 있도록 만들어주고 다음과 같이 정의할 수 있다

  1. JRE의 구현체 ( 실제로 JAVA 실행환경을 만들어준다는 의미 )
  2. java 클래스를 실행하기 위해 런타임시에 생성되는 인스턴스 ( 동작주체 )
  3. 바이트코드를 플랫폼에 맞는 기계어로 바꿔주는 도구

JVM의 동작

JVM은 Main 메서드를 찾아서 실행시키고, 플랫폼에 무관하게 자바 어플리케이션이 동작하게 해준다
.java 파일을 컴파일하여 바이트코드로 이루어진 .class파일을 생성하고 실행시킨다

JVM이 처리해주는 작업들은 다음과 같다

  1. 코드 읽기 / 검증 / 실행
  2. 런타임 환경 제공
  3. 메모리 영역 할당
  4. 레지스터 세팅
  5. Heap영역 Garbage Collection
  6. Application에 발생한 오류보고
  7. .class 형식 제공

구조

크게 ClassLoader / Memory 영역 / 실행엔진 으로 나뉘어서 동작한다

  1. ClassLoader
    .class 파일들을 읽고, 검증한다음 초기화하는 작업을 수행한다
    이러한 과정을 Loading / Linking / Initialization 으로 부른다

  2. Memory 영역
    크게 Method( Static ) / Heap / Stack / PC 레지스터 / Native Method Stack 으로 나뉜다
    이 중 중요한 부분은 Method / Heap / Stack 영역이다

    • Method ( Static ) : 클래스의 구조를 저장하는 영역 ( 클래스, 메서드, 필드 등 )
    • Heap : 동작 시에 참조형 타입의 데이터를 관리하는 영역
    • stack : Thread별로 메서드 실행 시 할당 및 반환되는 영역
  3. 실행엔진
    메모리에서 데이터를 읽고 실행하는 역할을 한다
    Interpreter나 Garbage Collector, JIT 컴파일러 등이 있다

    • Interpreter : 바이트코드를 한줄씩 읽고 실행
    • JIT 컴파일러 : 인터프리터의 성능향상을 위해 반복적으로 실행되는 코드를 캐싱하는데 사용
    • Garbage Collector : Heap 영역에서 더이상 사용되지 않는 메모리 반환

Garbage Collection

앞서 설명한 Garbage Collector가 실행하는 프로세스로 메모리관리에 사용된다
더이상 Heap영역에 필요없는 객체를 처리하는 작업이다

객체의 자원회수를 자동으로 해주기때문에 부주의로 인한 메모리낭비를 줄일 수 있다는 장점이 있지만,
자원 회수시점과 상태추적에 들어가는 자원소모가 있다는 단점도 있다.

GC가 적용되는 대상은 더이상 아무런 곳에서도 참조하지않는 객체이다
주로 null을 명시해줌으로써 GC대상이 되게 할 수 있다

GC의 주요특징으로는 STW( Stop thw World ) 가 있다
이는 GC작업이 완료될 때까지 Thread가 정지함을 의미한다.

Heap영역은 크게 Young Gen / Old Gen으로 나뉘는데 각각 아래와 같다

  1. Young Generation
    새로운 객체가 할당되는 영역으로 이 영역에 객체가 가득차면 Minor GC가 진행되고 속도가 빠르다

  2. Old Generation
    오랫동안 살아남은 객체들을 저장하는 영역으로 Young Generation보다 크다
    Young Generation에서 특정 시간이상 살아남은 객체들이 이 영역으로 옮겨진다
    이 영역에서 일어나는 Collection을 Major GC라고 부르며 STW시간이 더 길다

두 가지 영역 모두를 대상으로한 GC는 Full GC라고 부른다
이때, Young Generation은 Eden, Survivor 으로 나뉜다
Eden은 최초에 저장되는 영역이고 Survivor는 Eden이 가득찬 다음, GC가 일어나고 살아남은 객체가 저장되는 영역이다

Garbage Collector 종류

1. Serial Garbage Collector

싱글 스레드환경에서 동작

Young 영역에서는 앞서 설명한 것처럼 동작하고 Old 영역에서는 mark-sweep-compact 알고리즘을 사용한다

1. **살아있는 객체 식별 ( Mark )**
2. **Mark 하지 않은 객체 제거 ( Sweep )**
3. **살아있는 객체를 앞쪽부터 채우기 ( Compaction )**

의 과정으로 동작하며 그림으로 설명하면 다음과 같다

2. Parallel Garbage Collector

Serial GC와 동일하게 동작하나 멀티스레드 환경에서 동작한다

3. CMS Garbage Collector

Concurrent Mark-Sweep GC

위 구조에서 GC가 일어나면 겪게되는 과정을 알아보자


Survivor 에서 특정시간 이상 살아남은 객체들은 Old Generation으로 옮겨지고 나머지 객체들은 또 다른 Survivor 영역으로 이동된다


Old Generation 에서는 2번의 STW 이벤트가 발생한다

  1. Initial mark : 짧은 시간동안 살아있는 객체들을 mark한다
    1. 하나의 Thread를 사용하여 프로그램 동작과 동시에 mark하지 못한 객체들을 찾아낸다
  2. remark : 누락된 모든 살아있는 객체들을 mark한다

이후 2번의 STW이벤트를 거친후에 mark되지 않은 모든 객체들의 메모리를 반환시킨다


모든 과정에서 full GC가 일어나지 않는이상 압축은 하지않는다

4. G1 Garbage Collector

이름이 G1( Garbage First ) 인 이유는 Garbage만 있는 지역을 먼저 회수해서다
CMS GC를 더 효율적으로 만든 버전이다


기본적으로 Minor GC만 수행된다
만약 Old gen 비율이 임계 값을 초과하면 Major GC와 Minor GC가 왔다갔다 하면서 동작한다

이후 Space Reclamation 단계에 진입하게되면 Mixed GC가 수행된다

💡 Mixed GC

Young / Old 영역 모두의 Garbage 수집
Minor GC + Old 영역 GC

Mixed GC는 아래의 과정을 거친다


Young / Old Generation으로 나누지않고, 일정한 크기의 region으로 나눈다

이 region의 크기는 JVM을 시작할때 설정할 수 있으며 일반적으로 1~32mb크기를 가진 약 2000개의 region으로 나눈다


region들은 개념적으로 Eden, Survivor, Old Generation, Humongous로 나눌 수 있다


먼저 EdenSurvivor 영역에 해당하는 region에 대해 Minor GC가 일어나면 STW가 발생하고
살아남은 객체들은 적절한 크기의 Old Generation이나 survivor로 이동된다

이 작업은 멀티스레드 환경에서 병렬적으로 이루어진다


Minor GC 가 끝날때까지 Old에서 참조하는 survivor region이 있는지를 찾고 해당 reigon에서 생존한 객체를 찾아 mark한다

  • 모든 객체가 Grabage인 regionOld region내에 살아있는 객체를 찾는다
  • 발견된 region의 메모리를 반납하고 모든 region에 대해 살아있는 객체를 판단한다

  • 아직 사용중인 객체들을 모아서 Young GC가 일어날때 같이 동작한다
  • 살아있는 객체의 비율이 적은 region부터 처리하며 생존한 객체는 미사용 영역으로 압축한다

0개의 댓글