Garbage Collection 에 대한 이해
Overview
JVM 의 Garbage collection(이하 GC) 에 대해서 정리해봅니다.
What is GC?
JVM Memory 는 여러 영역으로 구분되어 있다.
Heap 영역은 new 연산자 등으로 생성된 객체와 배열 등을 저장하는 공간이다. Heap 영역에 생성된 객체나 배열은 다른 객체에서 참조될 수 있다. GC 는 바로 이 Heap 영역에서 발생한다.
만약 Java 로 작성된 프로그램이 종료되지 않고 계속 실행된다면 메모리 안에 데이터가 쌓이기만 할 것이다. 이러한 문제를 GC 를 통해 해결한다.
어떻게 해결한다는 것일까? JVM 은 도달할 수 없는 객체(unreachable)을 GC 의 대상으로 설정한다. 어떤 객체가 도달할 수 없는 객체가 되는지는 다음 코드를 보면 이해할 수 있다.
public class Main {
public static void main(String[] args) {
Person person = new Person("a", "곧 참조되지 않음");
person = new Person("b", "참조가 유지됨.");
}
}
최초로 person 을 초기화할 때 생성된 a
는 바로 다음 줄에서 person 에 b
가 재할당되며 도달할 수 없는 객체가 된다. 이제 a
는 다음 GC 가 일어날 때 메모리에서 해제되게 된다.
Stop the world
The World! 시간이여, 멈춰라! - 죠죠의 기묘한 모험 중
GC 을 실행하기 위해 JVM 이 애플리케이션 실행을 멈추는 것. Stop the world 가 발생하면 GC 를 실행하는 쓰레드를 제외한 나머지는 모두 작업을 멈춘다. GC 작업을 완료한 이후에야 중단했던 작업을 다시 시작한다. 어떤 GC 알고리즘을 사용하더라도 stop the world 는 발생하며, 대개 GC 튜닝이란 stop the world 시간을 줄이는 것이다.
Java 는 프로그램 코드에서 메모리를 명시적으로 지정하여 해제하지 않는다. 가끔 명시적으로 해제하려고 해당 객체를 null
로 지정하는 것은 큰 문제가 되지 않으나, System.gc()
를 호출하는 것은 시스템의 성능에 매우 큰 영향을 끼치므로 절대로 사용하면 안된다. 심지어 System.gc()
는 실제로 GC 가 일어날 것이라는 보장을 해주지 않는다.
GC 가 발생하는 2가지 영역
Java 에서는 개발자가 프로그램 코드로 메모리를 명시적으로 해제하지 않기 때문에 가비지 컬렉터(Garbage Collector)가 더 이상 필요없는 (쓰레기) 객체를 찾아 지우는 작업을 한다. 이 가비지 컬렉터는 두 가지 전제 조건 하에 만들어졌다.
- 대부분의 객체는 금방 접근 불가능 상태(unreachable)가 된다.
- 오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다.