본문 바로가기
Backend/Java

JVM Stack / Heap - GC

by DooDuZ 2024. 6. 19.

 

https://techvidvan.com/tutorials/java-virtual-machine/

 

 

Stack

JVM 내부에서의 스택은 스레드(Thread)가 독립적으로 실행되는 메모리 영역을 의미한다. Stack 영역에 스레드가 올라가고, 스레드마다 Call Stack / Program Counter Resister / Native Method Stack이 할당된다. 

 

Call Stack

메서드가 실행되면 메서드 정보를 담은 Stack Frame이 Call Stack으로 push 된다. 이때 Call Stack은 지역 변수 정보를 담은 Local Variable Array, 연산 정보를 담은 Operand Stack, 호출된 메서드에 대한 포인터 등이 포함되어 있다. 

public static void main(String[] args) {
    int a = 5;
    int b = 6;

    printSum(a,b);
}

static void printSum(int number1, int number2){
    int sum = number1 + number2;
    System.out.println(sum);
}

 

위 코드가 동작하는 과정을 따라가며 stack frame이 어떻게 생성되는지 알아보자.

 

호출 / Push

 

1. main 메서드가 실행되면서 Stack Frame이 Call stack에 삽입되된다.

2. printSum이 호출되면서 새로운 stack frame이 삽입된다. number1과 number2에 메서드 파라미터로 전달받은 5와 6이 대입되고, 오퍼랜드 스택에 하나씩 삽입된 뒤 연산이 일어난다.

3. System.out.println이 호출되면서 새로운 스택 프레임이 삽입된다. 파라미터로 연산 결과인 sum이 전달된다.

 

종료 / POP

 

출력이 완료되고 메서드 블록이 끝나면 해당 스택프레임은 콜 스택에서 pop 되며 메모리에서 해제된다. 이후 pointer에 저장된 printSum으로, printSum에선 이전 호출자인 main으로 돌아가서 마지막 pop이 일어나고 스레드는 종료된다.

 

Heap / GC

https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

 

Java의 모든 참조 타입 인스턴스는 Heap에 저장되며 stack영역에선 참조값을 통해 접근하게 된다. Heap은 JVM Garbage Collector에 의해 자동으로 메모리가 관리된다. GC가 작동하면 모든 스레드는 동작을 멈추는데 이를 Stop The World라고 한다. GC는 참조되지 않는 값을 찾아 마킹하고(Mark) 메모리에서 해제(Sweep)한다. Old Generation의 경우 Sweep 후 분산된 객체들을 모으는 Compact과정이 추가된다.

👉 이 글에선 Serial GC나 Parallel GC의 경우를 가정한다. GC 알고리즘에 따라 과정이 크게 다를 수 있다. ex) G1 GC

 

Minor GC

Young Generation에서 일어나는 GC. eden이 가득 차서 더 이상 메모리를 할당할 수 없는 경우 Garbage Collector는 해당 영역에서 참조되지 않은 값을 찾고 메모리를 해제한다. 이후 살아남은 인스턴스를 survivor영역으로 복사하는데, 이때 인스턴스 헤더의 age가 1 증가하게 된다.

 

survivor 영역은 한쪽만 데이터를 가지고 있으며, Minor GC가 일어날 때마다 데이터를 반대쪽 survivor 영역으로 옮기고 기존 영역을 비우게 된다. 이때도 역시 인스턴스의 age는 1 증가하며, age가 임계값에 도달하는 인스턴스는 Old Generation으로 이동한다.

 

Minor GC의 경우 Stop the World의 시간이 그렇게 길지 않기 때문에 애플리케이션의 성능에 미치는 영향이 상대적으로 적다.

 

Major GC(Full GC)

Old Generation이 가득 차면 Major GC가 일어난다. 위의 Minor GC에선 Mark와 Sweep 이후 살아남은 인스턴스를 비어있는 survivor로 옮기며 마무리 됐지만, Major GC에선 Sweep 후 단편화된 메모리를 없애는 작업인 Compact가 일어난다. 흩어진 메모리를 가깝게 옮기는 작업이라고 이해하면 좋다. Major GC의 경우 Minor GC보다 훨씬 긴 Stop The World가 발생하기 때문에 자주 일어나는 경우 애플리케이션의 심각한 성능 저하를 일으킬 수 있다.

'Backend > Java' 카테고리의 다른 글

Virtual Thread  (0) 2024.08.05
Serial GC / Parallel GC / G1 GC  (0) 2024.06.19
Java Compile  (2) 2024.06.07