가비지(Garbage)와 가비지 컬렉션(Garbage Collection)
1. 가비지 (Garbage)
가비지란 응용프로그램에서 더 이상 사용되지 않는 메모리이다. 자바 응용프로그램에서 new 연산자를 이용하여 시스템으로부터 할당받아 사용하다 더 이상 사용하지 않는 객체나 배열 메모리가 가비지가 된다.
더 이상 사용하지 않는다는 뜻은 객체나 배열을 가리키는 레퍼런스가 하나도 없음을 의미한다.
2. 가비지 컬렉션 (Garbage Collection)
가비지는 더 이상 참조되지 않기 때문에 가비지가 차지하고 있는 메모리 공간은 회수되어야 한다. 가비지가 많아지면 상대적으로 자바 가상 기계에서 응용프로그램에게 할당해줄 수 있는 가용 메모리의 양이 줄어들게 된다.
자바에서는 시간이 지날수록 가비지가 점점 늘어나게 된다. 최악의 경우, 자바 가상 기계의 가용 메모리의 양이 0이 되면 자바 응용프로그램은 더 이상 실행될 수 없게 된다.
이런 경우를 대비하여, 자바 가상 기계는 가용 공간이 일정 크기 이하로 줄어들게 되면 자동으로 가비지를 회수하여 가용 메모리 공간을 늘린다. 이것을 "가비지 컬렉션"이라고 부른다.
가비지 컬렉션을 수행하는 주체를 가비지 컬렉터(garbage collector)라고 한다. 자바 가상 기계는 가비지 컬렉터의 역할을 수행하기 위해서 가비지 컬렉션 스레드(garbage collection thread)를 두고 있다.
가용 메모리가 거의 없어지는 극한 상황은 잘 일어나지 않기 때문에 메모리 부족으로 인한 가비지 컬렉션은 보기가 쉽지 않다. 그리고 자바 가상 기계의 내부 알고리즘의 판단으로 인해서 가비지 컬렉션이 수행되기 때문에, 이 가비지 컬렉션이 언제 일어나는지 알기 어렵다.
비교적 큰 규모의 자바 프로그램 개발 경험을 가진 개발자들은 가끔 자신이 개발한 프로그램을 테스트하는 도중 프로그램의 실행이 일시적으로 중단된 것처럼 보이는 경험을 한 적이 있을 것이다. 규모가 큰 자바 프로그램은 실행 중 비교적 많은 양의 가비지를 생산한다. 그러다가 가끔 가용 메모리가 부족해지는 경우가 있는데, 이때 가비지 컬렉터가 실행되며 자바 프로그램은 실행을 멈추고 가비지 컬렉션이 끝나기를 기다리게 된다. 이것이 사용자의 눈에는 프로그램이 중단된 것처럼 보인다. 이러한 이유로 자바는 실시간 처리 응용에는 부적합한 것으로 알려져 있다.
(이미지 출처: <https://d2.naver.com/helloworld/329631>)
위의 이미지는 자바 응용프로그램에서 객체를 생성 했을때, 자바 가상 기계 내에서 어떤 식으로 메모리가 소비 되는지를 나타낸다.
왼쪽의 공간을 스택(Stack)이라고 하는데, 이 공간에는 실행중인 메소드의 지역 변수 등의 정보가 들어간다.
가운데의 넓은 공간을 힙(Heap) 영역이라고 부르는데, 이 힙에 객체가 생성된다.
스택 영역에 생성된 레퍼런스 변수가 화살표로 연결된 객체를 참조하고 있는 것이다. 그런데, 힙 영역에 화살표로 연결되지 않은 객체들이 보일 것이다. 저 객체들이 바로 참조되지 않은 객체들, 다시 말해 가비지이다. 자바 가상 기계는 저러한 가비지들이 메모리를 낭비하지 않게 하기 위해서 가비지 컬렉션을 통해서 할당된 메모리를 수거한다.
3. 가비지 컬렉션 강제 수행
응용프로그램에서 System 또는 Runtime 객체의 gc() 메소드를 호출하게 되면, 가비지 컬렉션을 수행하게 만들 수 있다.
i.e. System.gc(); // 가비지 컬렉션 작동 요청
정확하게 말하자면, gc() 메소드를 이용하게 되면 "이쯤에서 가비지 컬렉션이 일어나야 하지 않을까?" 라는 식으로 자바 가상 기계에게 알림을 주게 된다. 그 후에 가비지 컬렉션이 일어날지에 대한 여부는 온전히 자바 가상 기계의 선택에 달려있다.