<참조 - 네이버 개발자 센터 - http://helloworld.naver.com/helloworld/1329>


gc(garbage collection)이란?

gc에 대해 알기 위해서는 stop-the-world 라는 것에 대해서 알아야한다.

stop-the-world란 gc를 실행하기 위해서 jvm애플리케이션이 실행을 멈추는 것이다

gc를 실행하는 스레드를 제외한 모든 스레드는 정지한다. 

결국 gc 튜닝이란 stop-the-world의 시간을 최소로 하는 것을 말한다고 할 수 있다. 


자바 프로그램에서는 메모리를 명시적으로 지정하여 해제 할 수 없다. 

해당 객체를 null로 지정하거나 (이 것은 큰 문제는 안됨)

system.gc()와 같은 함수를 사용하는 방법은 있으나 사용하면 안 된다. 

성능에 지대한 영향을 끼치기 때문이다.


자바코드에서는 메모리를 명시적으로 해제하지 않기때문에 가비지컬렉터가 더 이상 필요 없는 객체를 지우는 것이다.


가비지 컬렉터(Garbage Collector)는 두 가지 가설에 의해서 만들어졌다. 

이 가설을 "Weak generational hypothesis"라고 하는데

 * 대부분의 객체는 금방 접근 불가능한 상태가 된다. 

 * 오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다.


이러한 가설의 장점을 최대한 살리기 위해서 Hospot VM에서는 크게 2개의 물리적 공간으로 나누었다. 


Young영역과 Old영역


Young영역은 무엇인가?

새롭게 생성한 객체의 대부분이 여기에 위치한다. 

대부분의 객체가 금방 접근 불가능한 상태가 되기 때문에 많은 객체가 Young영역에 생성되었다가 사라진다.

이 영역에서 객체가 사라질 때 minor GC라고 한다.


Old영역은 무엇인가?

접근 불가능한 상태로 되지 않아 Young영역에서 살아남은 객체들이 이 곳으로 복사된다. 

대부분 Young영역보다 크게 할당하며, 크게 할당된만큼 Young영역보다는 GC가 적게 일어난다.

이 영역에서 객체가 사라질 때 major GC(혹은 Full GC)가 발생한다고 한다.



 

Permanent Generation 영역은 무엇인가?

영원한 영역이라는 말은 아니다. 

객체나 억류된(intern)된 문자열 정보를 저장하는 곳이며, 여기서 GC가 일어나도 

major GC가 일어났다고 한다.





Old 영역에서 Young 영역으로 참조하고 있는경우에는 어떻게 처리하나?

=> 그래서 old영역에는 카드테이블(card table)이 존재한다. 

카드테이블은 Old영역에서 Young영역으로 참조하고 있는 정보를 담고 있으므로

모든 old영역의 참조를 뒤져본 후에 GC가 일어나는것이 아니라 카드테이블정보만 

보고 GC가 일어나게 되는 것이다. 



young 영역은 어떻게 구성되는가?

Eden영역과 survivor영역 2개로 구성된다. 총 3개의 영역으로 구성된다.


새로 생성된 객체는 Eden영역에 위치한다

Eden영역에서 GC가 한번 일어난 후에 살아남은 객체는 Survivor영역 중에 하나로 이동한다.

Eden영역에서 GC가 발생할 때마다 Survivor영역에는 살아남은 객체가 쌓이게 된다.

하나의 survivor영역이 가득차게 되면 모든 객체가 다른 survivor영역으로 이동하게 된다. 원래있던 survivor영역은 비어있는 상태가 된다.

- 이 과정을 반복하다가 계속해서 살아남아 있는 개체는 Old영역으로 이동하게 된다. 



이 메커니즘에 대해서 이해 하게 되면 

두 survivor영역에 모두 객체가 있거나, 두 영역 모두 사용량이 0이라면 시스템은 정상적이지 않다는 것을 판단 할 수 있게 된다. 


그렇다면 Old영역에서의 GC는 어떤 과정으로 처리되나?

기본적으로 Old영역이 가득차게 되면 GC가 일어난다. 

Old영역에서의 GC는 JDK 7 기준으로 5가지가 지원된다.

- serial GC

- parallel GC

- parallel Old GC

- Concurrent Mark & Sweep GC(이하 CMS)

- G1(Garbage First) GC


이 중에서 반드시 알아야 할 것은 운영서버에서는 serial GC를 절대 사용하면 안된다는 것이다. 


Serial GC는 어떤 방식으로 이루어지나?

Young영역에 대한 GC는 앞에 설명한 바와 같이 이루어진다. 

Old영역에서의 GC는 기본적으로 mark-sweep-compact라는 알고리즘을 사용한다. 


이 알고리즘의 첫 단계는 Old 영역에 살아 있는 객체를 식별(Mark)하는 것이다. 

그 다음에는 힙(heap)의 앞 부분부터 확인하여 살아 있는 것만 남긴다(Sweep)

마지막 단계에서는 각 객체들이 연속되게 쌓이도록 힙의 가장 앞 부분부터 채워서 객체가 존재하는 부분과 객체가 없는 부분으로 나눈다(Compaction).


Serial GC는 적은 메모리와 CPU 코어 개수가 적을 때 적합한 방식이다.


Parallel GC

Parallel GC는 Serial GC와 기본적인 알고리즘이 동일하다. 

그러나 Serial GC는 스레드가 한 개인것에 비해 Parallel GC에 쓰이는 스레드는 여러개다.

그래서 시리얼GC보다 더 빠르게 처리가 가능한 것이다. 


- parallel Old GC란?


- Concurrent Mark & Sweep GC 란?


- G1(Garbage first) GC 란?



****정리****

고급 개발자라는 것은 GC에 대한 명확한 이해와 함께 GC를 튜닝하는 관심과 능력을 가지고 있어야 된다고 한다. 

(네이버 개발자 센터에서 이 글의 원본을 쓰신 분이 한 말)

결국 대용량이나 거대한 프로젝트를 접해보신 분이 이러한 GC 튜닝을 해봐야겠다는 마음도 생겼기 때문이다. 

앞서 JDK에서 여러가지 GC를 제공하는 이유인 즉슨 가장 좋은 GC는 없다는 것이다. 그 서버의 상황과 하드웨어에 따라서

그에 맞는 GC를 제공해야 된다는 것이다. 

앞으로 고급 자바 개발자가 되야되겠다...

'JAVA' 카테고리의 다른 글

자바가 확장한 객체지향  (0) 2015.06.30
자바와 객체지향  (0) 2015.06.30
자바 스레드의 이해  (0) 2015.06.30
자바 메모리 구조 >>> 2  (0) 2015.06.30
자바 메모리 구조>>1  (0) 2015.06.30
Posted by slender ankles
,