GC란 가비지 컬렉션의 약자이며, JVM의 Heap영역에서 사용하지 않는 객체를 삭제하는 프로세스를 말한다.
GC의 대상은?
참조되지 않은객체 (UnReachable)이 수거 대상입니다.
heap 영역은?
heap 영역은 Young Generation과 Old Generation으로 나뉜다. Young은 Eden 영역과 Survivor 2개영역으로 총 3개의 영역으로 나뉜다.
객체가 생성할 때 그 객체는 Eden에 생성된다.
참조하지 않은 객체를 어떻게 구별하는가? Mark-Sweep 알고리즘과 Minor GC
객체에는 mark-bit 하나씩 할당된다. 프로세스가 작동할 때, 사용된 객체의 mark-bit은 1이 된다. mark-bit의 경우 일종의 chain으로 작동하여 참조하는 객체는 다른 객체를 불러오며 동시에 mark-bit을 1로 만든다.
새로 생성된 객체는 Eden에 저장된다. Eden에 꽉 차면 Minor GC가 작동한다. Minor GC는 heap영역의 1번지부터 마지막까지 하나씩 탐색한다. 탐색 과정에서 1인 것은 0으로 만들고 0인 것은 제거한다.
다시 프로세스가 수행되어 참조하는 객체는 0에서 1이 된다.
살아남은 객체는 어떻게 작동하는가? Young Generation
살아남은 객체는 서바이버 1로 이동한다.
에덴이 꽉 차면 minor GC가 작동한다. 서바이버 1과 에덴에서 살아남은 객체가 서바이버 2로 이동하며, compact된다.
에덴이 꽉차면 다시 minor GC가 작동한다. 에덴과 서바이버 2에서 살아남은 객체가 서바이버1로 이동한다.
살아남은 객체는 age bit이 1씩 올라간다. age bit의 한계치(Tenuring Threshold) 이상 반복할 경우 Old영역으로 이동한다.
Old Generation, Major GC
Young Generation에서 살아남은 객체는 Old Generation으로 승급Promption한다.
만약 Old Generation이 가득차면, Major GC(OutOfMemory, Stop-the-world)가 일어난다. JVM이 멈춘다.
GC 알고리즘들
Serial GC
스레드가 하나이다.
Mark - Compact Collection 알고리즘 : Compact 기능이 추가. Linked-list로 연결되어 free가 된 공간의 파편화를 없앰.
Parallel GC
Java 8 기본값
스레드가 여러개이다.
GC의 작동을 빠르게 Stop-the-world의 속도를 줄임
G1 GC
Java 9 기본값
Heap을 일정 크기의 Region으로 나눔.
Region의 참조 수준에 따라 Eden, Survivor, Old Generation으로 구분.
Minor GC가 모든 주소를 참조하지 않으므로 탐색 속도가 빠름
JVM에서 메모리 누수가 발생할까?
JVM에서도 메모리 누수가 발생할 수 있다. GC는 참조하지 않는 Unreachable한 객체를 제거 대상으로 간주하기 때문에 사용은 하지 않지만 계속해서 참조를 하는 경우가 있다면 메모리 누수가 발생할 수 있다.
GC를 개발자가 세팅할 수 있을까?
GC는 System.gc() 메소드를 통해 개발자가 의도적으로 실행이 가능하지만 권장하지 않는다. Stop-the-world 가 발생할 수 있어 시스템의 성능을 오히려 저하시킬 수 있다.
GC, 정확하게 JVM은 자바 버전이 올라감에 따라 성능이 발전한다. 그러므로 자바의 높은 버전을 사용하는 것을 추천한다.
사용자는 필요에 따라 GC 알고리즘, Tenuring Threshold을 변경할 수 있다. 힙 메모리의 최소 용량과 최대 용량을 설정할 수 있다.
첨언하자면, 이번에 GC를 공부하면서 인텔리제이 VM 세팅이 무엇인지 이해할 수 있었다. 최적화라고 해서 그냥 따라했었는데. 내가 설정한 힙 메모리 최솟값과 최댓값은 아래와 같다. 하고 나서 정말 빨라졌다! 이클립스, 인텔리제이 관계 없이 모두 변경하는 것 추천한다. (참고로 나는 램이 16기가이다)