내가 가장 설명할게 많은 가비지 컬렉터이다. 사실 가비지컬렉터 때문에 JVM 공부를 시작한게 크다. 그래서 더더욱 정감이 가는 부분이다. 하하... 결국 아는척 할게 많은 느낌이다. 어쨌든 한 번 시작해보겠다!!
가비지는 언제 생길까? 왜 생길까? 내용은 간단하다. 우리가 new 연산자를 이용해 객체를 생성한다. 그러면 메모리에 올라간다. 그때 이 객체를 지속적으로 사용하지 않고, 참조도 하지 않으면 그건 가비지가 된다. 그렇게 사용하지 않는 메모리가 생기는게 가비지가 생기는 과정이다. 아래는 내가 직접 그려본 가비지가 생기는 과정이다.
public class Date01 {
public static void main(String[] args) {
int a = 0;
String str = "자바";
}
}

str = "바꾼거";

위와 같은 방식으로 처리된다. 이렇게 만들어지는 가비지를 자바에서는 unreachable object라고 하며, 이러한 unreachable object를 GC가 처리한다.
1. Stop The World
가비지 컬렉션을 실행하기 위해 JVM이 애플리케이션의 실행을 멈추는 작업이다. GC가 실행될 때는 GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업이 중단되고, GC가 완료되면 작업이 재개된다.
( 그래서 언제 멈추는건데 ==> Young 영역이나 Old 영역이 꽉차면 )
당연히 모든 쓰레드들의 작업이 중단되면 애플리케이션이 멈추기 때문에, GC의 성능 개선을 위해 튜닝을 한다고 하면 보통 stop-the-world의 시간을 줄이는 작업을 하는 것이다.
또한 JVM에서도 이러한 문제를 해결하기 위해 다양한 실행 옵션을 제공하고 있다.
2. Mark and Sweep
Stop The World를 통해 모든 작업을 중단시키면, GC는 스택의 모든 변수 또는 Reachable 객체를 스캔하면서 각각이 어떤 객체를 참고하고 있는지를 탐색하게 된다. 그리고 사용되고 있는 메모리를 식별하는데, 이러한 과정을 Mark라고 한다. 이후에 Mark가 되지 않은 객체들을 메모리에서 제거하는데, 이러한 과정을 Sweep이라고 한다.
가비지 컬렉터는 두 개로 나눠져 있다. MinorGC와 MajorGC 이 두 개의 GC가 우리의 메모리를 깔끔하게 청소해준다. 동시에 공간도 각각 나눠져 있다. YoungGeneration 영역과 OldGeneration 영역이다. 어떤 차이가 있는지는 밑에서 마저 설명하겠다.
YoungGencration 영역은 새로 생성된 객체가 올라가는 곳이다. 말 그대로 Young하다. 그리고 또 다르게 말하면 일회석 객체들이 올라가는 곳이기도 하다. 그렇게 YoungGencration 영역에서 오래 있다가 OldGeneration 영역으로 옮겨지기도 한다.
Young영역의 구조에는 두 가지 총 세 가지 영역이 더 있다. (Eden 영역 / Survivor 영역(2) )
Eden 영역 : 새로 생성된 객체가 할당(Allocation)되는 영역 ( 해당 영역이 꽉 찼을 때 MinorGC가 발생 )
Survivor 영역 : 최소 1번의 GC 이상 살아남은 객체가 존재하는 영역

작동 순서

이 외에도 youngGeneration 영역에는 CardTable이라는 것이 또 있다. 카드 테이블은 oldGeneration 영역의 객체들이 참조하는 YoungGeneration 영역의 객체가 있을 수 있으니, 참조 관계를 기억하고 있는 것이다. 이를 통해 OldGeneration 영역에서 참조하는 YoungGeneration 영역의 객체를 지우지 않고 유지한다.
young영역에서 오래 살아남은 객체는 Old 영역으로 Promotion됨을 확인할 수 있다.
그리고 Major GC는 객체들이 계속 Promotion되어 Old 영역의 메모리가 부족해지면 발생하게 된다. Young 영역은 일반적으로 Old 영역보다 크기가 작기 때문에 GC가 보통 0.5초에서 1초 사이에 끝난다.
그렇기 때문에 Minor GC는 애플리케이션에 크게 영향을 주지 않는다. 하지만 Old 영역은 young 영역보다 크며 young 영역을 참조할 수도 있다. 그렇기 때문에 MajorGC는 일반적으로 MinorGC보다 시간이 오래 걸리며, 10배 이상의 시간을 사용한다.
이름이 Major한 GC MajorGC는 사실 크게 별게 없다. MinorGC에서 많은 일을 처리하다보니 MajorGC는 메모리가 꽉 찼을 때 한 번 청소해주는 것 말고는 크게 언급할 내용이 없다.
| GC종류 | minorGC | majorGC |
|---|---|---|
| 대상 | YoungGeneration | OldGeneration |
| 실행시점 | Eden영역 꽉찬 경우 | Old 영역이 꽉 찬 경우 |
| 실행속도 | 빠르다 | 느리다 |
JVM 공부기록 정리를 이렇게 끝마쳤다. 이제 남은 일은 ClassLoader를 좀더 자세히 공부하고, 예제를 남기는 정도가 될 것 같다. 작년에 공부하고 정리한 내용을 기억을 더듬으며 다시 새로운 블로그에 옮기는 과정이었는데 새삼 자바로 for문 겨우 돌리던 내가 이런 것도 공부했던게 기특하기도 하고, 여태 뭐했길래 아직도 이러고 있나 한심하기도 하는 많은 생각이 들었다. 그래도 어쨌든 나아갈거니까 그리고 지금은 좀 더 열심히 해야겠다 싶다.