자바에서는 불필요한 메모리 할당을 제거하기 위해 가비지 컬렉션이라는 기능을 제공한다. JVM의 Heap 영역에 동적으로 할당된 메모리 중에서 사용하지 않는 부분을 주기적으로 회수하는 작업이다. C, C++을 사용하면 alloc을 한 후에 free를 반드시 해줘야 됐었다는 사실이 기억날 것이다. 자바에서는 free를 JVM에 탑재된 가비지 컬렉터가 알아서 해준다. 그렇기 때문에 개발자가 실수로 free를 안해줘서 OOM(Out Of Memory) 같은 Exception이 발생할 일이 적고 오로지 개발에만 더 집중할 수 있다는 장점이 있다. 그렇다고 메모리에 대해 전혀 신경을 쓰지 않아도 되는 것은 아니니 필요한 상황에는 생성된 객체를 제거하거나 메모리 할당을 해제 해주어야 하는 경우도 종종있다.
그런데 자바의 이런 편리한 기능에도 장점만 있는 것은 아닌데, 가비지 컬렉션이 개발자가 컨트롤 하는 것이 아니기 때문에 언제 발생할 지 알 수 없다. 언제 발생할지 알 수 없다는 것은 프로그램의 특징에 따라서 치명적인 문제가 될 수도 있다. 왜냐면 가비지 컬렉션이 일어날 때 JVM의 다른 모든 동작들이 멈추기 때문이다. 예를 들어서 실시간으로 계속 프로세싱이 필요한 프로그램인데 중간에 가비지 컬렉션이 일어나게 되면 그 찰나의 데이터들을 놓치게 됨으로써 예상된 결과를 보지 못하거나 디버깅이 어려워질 수도 있다. 또 가비지 컬렉션은 다른 동작을 멈춘다는 오버헤드가 있기 때문에 너무 자주 발생하게 되면 성능에 문제가 될 수도 있다.
가비지 컬렉션은 Heap 영역에 생성된 객체들을 수거하는 것인데 아무 객체나 랜덤으로 수거하지는 않는다. 위의 그림에서 나타나듯이 Method 영역, Stack 영역에서 참조하고 있는 객체들은 제외 대상이고 참조되고 있지 않는 대상들이 수거가 된다.
Heap 영역은 조금 더 효율적인 운영을 위해서 위와 같이 구조가 분리되어 있다. new 키워드를 이용해서 객체를 생성하면 Eden 영역에 객체가 생성이 된다. 그 후에 Eden 영역이 가득 차게되면 Minor 가비지 컬렉션이 일어나고 살아남을 때마다 age가 올라가게 되고 특정 age가 넘으면 survival 영역에서 old generation 영역으로 이동하게 된다. 그러다가 old generation 부분까지 가득 차게 되면 Major 가비지 컬렉션이 실행되게 된다. 이 때 old generation 영역의 객체 중에 참조되고 있지 않은 객체들을 회수가 된다. 이 때 JVM의 모든 동작이 멈추는데 이를 Stop The World 부른다.
가비지 컬렉션은 생각보다 간단한 프로세스로 진행된다. 실제로 내부적으로는 가비지 컬렉션 하는 알고리즘도 존재하는데 등은 버전에 따라 조금씩 다른 것으로 알고 있다. 더 궁금한 내용이 있다면 구글링을 추천한다.
'Java' 카테고리의 다른 글
Java - Abstract Class와 Interface의 차이 (0) | 2022.08.04 |
---|---|
Java - String pool (0) | 2022.08.03 |
Java - 컴파일 과정 (0) | 2022.08.01 |
Java - HashSet, LinkedHashSet, TreeSet 차이 (0) | 2022.07.31 |
Java - HashTable이란? (0) | 2022.07.30 |