당신이 올바른지. 설명하는 특정 형태의 가비지 콜렉션을 " 참조 횟수 "라고합니다. 가장 간단한 경우에 개념적으로 작동하는 방법 (적어도, 대부분의 최신 참조 횟수 구현은 실제로는 다르게 다르게 구현 됨)은 다음과 같습니다.
- 객체에 대한 참조가 추가 될 때마다 (예 : 변수 또는 필드에 할당되거나, 메소드에 전달되는 등) 참조 횟수가 1 씩 증가합니다.
- 객체에 대한 참조가 제거 될 때마다 (메소드가 반환되고 변수가 범위를 벗어남, 필드가 다른 객체에 다시 할당되거나 필드를 포함하는 객체가 가비지 수집 됨) 참조 횟수가 1 씩 감소합니다.
- 참조 카운트가 0에 도달하면 더 이상 객체에 대한 참조가 없으므로 아무도 더 이상 사용할 수 없으므로 가비지이므로 수집 할 수 있습니다
그리고이 간단한 전략은 당신이 결정하는 문제를 정확히 가지고 있습니다 : 만약 A가 B를 참조하고 B가 B를 참조한다면, 그들의 참조 카운트는 모두 1보다 작을 수 없으며 , 이는 결코 수집되지 않을 것입니다.
이 문제를 처리하는 방법에는 네 가지가 있습니다.
- 무시해. 메모리가 충분하면주기가 작고 드물고 런타임이 짧을 경우주기를 수집하지 않고 벗어날 수 있습니다. 쉘 스크립트 인터프리터를 생각해보십시오. 쉘 스크립트는 일반적으로 몇 초 동안 만 실행되며 많은 메모리를 할당하지 않습니다.
- 사이클에 문제가없는 다른 가비지 수집기와 참조 횟수 가비지 수집기를 결합하십시오 . CPython은이를 수행합니다. 예를 들면 다음과 같습니다. CPython의 기본 가비지 수집기는 참조 횟수 수집기이지만 때때로주기를 수집하기 위해 추적 가비지 수집기가 실행됩니다.
- 주기를 감지하십시오. 불행하게도, 그래프에서 사이클을 감지하는 것은 다소 비용이 많이 드는 작업입니다. 특히, 추적 콜렉터와 거의 동일한 오버 헤드가 필요하므로 그 중 하나를 사용할 수도 있습니다.
- 순진한 방식으로 알고리즘을 구현하지 마십시오. 1970 년대 이래로 사이클 감지와 레퍼런스 카운팅을 단일 작업에서 영리한 방식으로 결합하여 수행하는 것보다 훨씬 저렴한 여러 흥미로운 알고리즘이 개발되었습니다. 별도로 또는 추적 수집기를 수행합니다.
그건 그렇고, 가비지 수집기를 구현하는 다른 주요 방법 (그리고 이미 위에서 몇 번 암시 했음)은 추적 입니다. 추적 수집기는 도달 가능성 개념을 기반으로합니다 . 당신은 몇 가지로 시작 루트 세트 당신이 알고 항상 도달 (전역 상수, 예를 들어, 또는 Object
당신이 거기에서 클래스, 현재 어휘 범위, 현재 스택 프레임) 및 추적 루트 세트에서 연결할 수있는 모든 개체를 한 후, 전이 폐쇄가있을 때까지 루트 세트에서 도달 할 수있는 오브젝트 등에서 도달 할 수있는 모든 오브젝트. 폐쇄 되지 않은 모든 것은 쓰레기입니다.
주기는 자체 내에서만 도달 할 수 있지만 루트 세트에서는 도달 할 수 없으므로 수집됩니다.