이번 포스팅에서는 Java의 주요 기능 중에 하나인 Garbage Collection에 대해 알아보려 한다.
프로그램을 개발하다가,
필요한 데이터를 사용하기 위해 메모리를 사용하고 이후 데이터를 사용하여 개발하는 작업이 완료되었을 때, 사용한 메모리를 그대로 둔다면
더 이상 활용되지도 않는 데이터를 위해 메모리를 사용하고 있는 것으로
한정된 자원인 메모리에서 상당히 큰 낭비를 초래한다.
이를, 다시 말해 ✅메모리 누수라 한다.
또한, 이를 방지하기 위해 사용한 메모리에 대한 반납이 요구되는데 이를 사용자가 직접 때에 맞게 반납하도록 처리하는 작업은 상당히 까다롭다.
여기서, 이러한 요구사항들을 모두 충족하는 것이 Java의 Garbage Collection이다.
- Heap 영역에 있는 데이터가 더 이상 활용되지 않을 때 해당 데이터를 자동으로 반환한다.
기능을 보면 C/C++에서의 무언가 비슷한 게 떠오를 것이다.
그렇다.
과 같다고 보면 된다.
C/C++에서는 동적할당 받은 메모리의 반납을 개발자가 직접 해줘야 하지만, Java에서는 이 역할을 JVM의 Garbage Collector를 통해 자동으로 수행한다.
다음으로,
즉, 어떤 알고리즘으로 동작하는지 알아보자.
현재까지 Garbage Collection에서 사용되는 정말 다양한 알고리즘들이 있다.
- Reference Counting Algorithm
- Mark-and-Sweep Algorithm
- Mark-and-Compact Algorithm
.
.
.
하지만, 이번 포스팅에서는 그 중 하나인 Reference Counting Algorithm에 대해 다루어 보려고 한다.(사실, 다른 알고리즘들은 잘 모른다.😅)
이 알고리즘은 reference count 변수를 통해 객체의 참조 유무를 판단하는데 자세한 내용은 다음과 같다.
객체가 생성되면 해당 객체가 저장되어 있는 주소(Heap)에서 실제 value와 함께 reference count라는 변수가 1로 초기화된 상태로 저장된다.
String A = new String("abc");
reference count의 예제로 위 코드를 그림으로 나타내면 다음과 같다.
이때, 다음 코드를 추가하면 어떻게 진행되는지 보자.
String B = A;
위와 같이 Heap 영역에서 1000번지 주소를 참조하는 객체가 1개 더 늘어남으로써 reference count의 값이 1 증가한 것을 볼 수 있다.
최종적으로 reference count = 0일 때, Garbage Collection에 의해 해당 메모리를 Heap에서 삭제한다.
Referenc Counting Alogrithm은 reference count 변수의 증감을 통해 객체의 참조 유무를 판단하므로 빠르고 Java 이외에 Garbage Collection 기능이 없는 언어에서도 구현이 쉽다는 장점이 있다.
✋ 하지만,
Heap 영역의 메모리를 할당 받은 객체의 수가 많을수록 각 객체의 reference count 변수를 매번 검사해야 하기 때문에 부하가 심하다. 또한, 객체들 간의 참조(Circular Reference - 연결 리스트)가 일어나는 경우 ✅순환 참조 오류로 참조가 해제?되어(아래 그림에서는 변수 A를 의미) Garbage Collection에 의해 해당 메모리가 삭제되어야 함에도 불구하고 해당 객체를 참조 중인 다른 객체에 의해 삭제되지 않는 상황이 발생한다.