정적
으로 할당한 메모리 영역동적
으로 할당한 메모리 영역public class Main{
public static void main(String[] args){
int num1 = 10;
int num2 = 5;
int sum = num1 + num2;
String name = "던";
System.out.println(sum);
System.out.println(name);
}
}
위와 같이 작성했을 때, Local Variable(지역변수)들 중
Primitive 타입
변수들은 stack에 호출순서대로 LIFO구조로 저장됨Class 타입
변수(ex. String)는 Heap영역에 할당됨이후 함수의 맨 마지막 } 를 만나서 함수가 종료되면 Stack에 있는 Local Variable은 다 pop되고 Heap영역에 Class 타입의 변수는 남아있게 된다.
이처럼 던: String
변수는 Unreachable Object(참조되지 않는 객체)
가 되어서 GC의 대상이 된다.
참조되지 않는 객체를 찾아서 삭제하는 것이 목표!
- [Mark] GC가 Stack의 모든 변수를 스캔하면서 각각 어떤 객체를 참고하고 있는지 찾아서 마킹한다.
- [Mark] Reachable Object가 참조하고 있는 객체도 찾아서 마킹한다.
- [Sweep] 마킹되지 않은 객체를 Heap에서 제거한다.
앞서 설명을 참고해서 위 그림을 보면 던: String
이 Unreachable Object이기 때문에 GC에 의해 제거될 것이다.
새로운 객체가 생성될 때 Eden영역에 할당됩니다.
위 사진처럼 Eden이 가득차게 되면 GC가 발생하게 됩니다.(Minor GC
)
그래서 Eden영역에서 Mark and Sweep
과정이 일어납니다.
여기서 살아남은 객체는 Survival 영역으로 이동합니다.(Unreachable 객체는 메모리에서 해제)
(Survival 영역 중 이미 객체가 존재하는 곳으로 우선적으로 이동)
따라서 GC는
Survival 0 | Survival 1
둘 중 한 영역은 계속 비어있도록 유지한다
앞선 Step1, 2 과정을 반복하면서 한 Survival 영역이 가득차게 된다면 GC가 발생하게 됩니다.(Minor GC
)
그래서 그 Survival 영역에서 Mark and Sweep
과정이 일어납니다.
여기서 살아남은 객체는 다른 Survival 영억으로 이동합니다.(Unreachable 객체는 메모리에서 해제)
이때, 다른 Survival 영역으로 이동한 객체는 Age값이 증가
합니다.
(그래서 색깔이 좀 더 진하게 표현했습니다.)
Step 1, 2과정을 진행하다가 아래와 같이 한 Survival 영역이 가득 찼다면,
그 Survival 영역에서 Minor GC가 동작해서 Mark & Sweep
과정이 일어나고
다시 Step 3 과정을 진행한다.
위 Step 1, 2, 3을 반복하다가 Age값이 특정 값 이상이 되면 Old Generation 영역으로 옮겨진다.
위 Step 1, 2, 3, 4를 반복하다가 Old Generation이 가득차게 된다면
Old Generation에서 GC가 발생합니다.
Mark and Sweep과정에서 Compact과정이 추가된 것이다 Sweep을 하고 나서 살아남은 객체의 메모리상 물리적 위치가 군데군데 위치하게 되었을 때,
효율적으로 메모리 관리하고 메모리 파편화를 방지
하기 위해 메모리의 특정위치에 모이게 해 관리한다.
Inital Mark
에선 GC과정-1에 해당하는 Mark과정을 진행(Stack 모든 변수 스캔
)Concurrent mark
에선 Inital Mark에서 마킹한 객체가 어떤 객체를 참조하고 있는지Remark
는 concurrent mark과정에서 application도 같이 수행되기에 그 동안에 새롭게 발생한 Unreachable object가 존재하는지 다시 마킹하는 과정