본문 바로가기

Study/Programming

자바 가비지, 컬렉션(Gabage Collection), 가비지 컬렉터(Gabage Collector)

가비지 컬렉션Garbage Collection이란, 시스템에서 더 이상 사용하지 않는 동적 할당된 메모리 블럭 혹은 개체를 찾아 자동적으로 다시 사용 가능한 자원으로 회수하는 것을 말한다. 시스템에서 가비지 컬렉션을 수행하는 부분을 가비지 컬렉터Garbage Collector라고 하며, 최초의 가비지 컬렉터는 1958년에 존 매카시John McCarthy에 의해 리습Lisp 언어의 일부로 구현되었다. 가비지 컬렉션은 약자로 GC라고 부르기도 한다.

일반적인 가비지 컬렉터 알고리즘(Algorithm)은 다음과 같이 동작한다
1. 더 이상 프로그램에서 사용하지 않을 개체Object를 찾아낸다.
2. 해당 개체가 사용하는 리소스를 회수한다.

위치

: 힙 메모리 영역에 존재(JVM은 New/Young 영역과 Old 영역에 대해서만 GC를 수행

더보기
JVM 메모리 구조

JVM 메모리 구조

Heap 메모리 구조
Young 영역 : 생긴지 얼마 안되는 객체를 저장하는 장소
Old 영역 : 생성된지 오래된 객체를 저장하는 장소
Perm 영역 : Code가 올라가는 부분이므로 GC가 일어날 필요가 없다.(Code가 모두 Load되면 일정한 수치를 유지.

역할

: 프로그램 수행 도중 해당 프로그램에서 생성된 객체(인스턴스)를 프로그램이 더 이상 사용하지 않을 때, 그 객체를 메모리에서 해제

장점 : 확보했던 메모리를 해제하지 않으면 계속 누적되어 결국 메모리 오버플로우(Overflow)가 발생하지만
사용 후의 오브젝트에 대해 신경쓰지 않아도 자동적으로 메모리 해제가 이루어져 프로그래밍에 집중 할 수 있다.

대상 객체

: 자신의 레퍼런스(주소)를 참조하는 변수 (레퍼런스 변수)가 없으면 가비지 컬렌션의 대상이 된다.
Book b = new Book()
b는 Book이라는 객체의 레퍼런스를 참조하는 레퍼런스 변수로 Book이라는 객체는 자신의 레퍼런스를 참조하는 변수 b가 존재 함으로 가비지 컬렉션의 대상이 될 수 없다.
하지만
Book b = new Book();
b = null;
b 변수에 null 값을 대입함으로 b는 어떠한 레퍼런스도 참조하지 않게 된다.(Book이라는 객체는 버림받게 되고 가비지 콜렉션의 대상이 된다.)

Book b = new Book(); //객체 1
Book c = new Book(); //객체 2
b = c;
이 경우 Book 객체를 생성하고 b와 c에 객체 레퍼런스를 하나씩 대입하였고 c를 b에 대입하였기 때문에 결국 b는 버림받아 가비지 콜렉션의 대상이 된다.

 C++의 경우 프로그래머가 객체 생성 시 생성자를 호출하며 객체를 메모리에서 해제할 때는 소멸자를 호출하여 메모리 관리
즉, 자바의 경우 가비지 콜렉터가 존재 하기 때문에 소멸자를 호출하지 않아도 된다.
그렇다면 자바의 소멸자는 없는 것인가? 그렇지 않다.
java.lang.Object 클래스에 protected void finalize() throws Thowable 이라는 소멸자가 존재하며 가비지 콜렉터가 이 finalize()메서드를 호출하여 객체를 메모리에서 해제한다.
가비지 콜렉터는 시스템에서 임의로 수행되기 때문에 System.gc()를 호출해도 우선순위를 높일 뿐이지 당장 쓰레기 수집을 하는 것은 아님

더보기
protected void finalize() throws Throwable 이 객체에의 참조는 이제 없으면 가베지 컬렉션에 의해 판단되었을 때에, 가비지 컬렉터에 의해 불려 갑니다. 서브 클래스는 finalize 메소드를 오버라이드(override) 해, system resource를 파기하거나 그 외의 클린 업을 실시하거나 할 수가 있습니다. 
finalize 의 일반적인 규약에서는, finalize 의 호출은, 아직 생존하고 있는 임의의 thread가 이 객체에 액세스 하는 방법은 없으면 JavaTM 가상 머신이 판단했을 경우에 행해집니다. 다만, finalize의 준비가 끝난 것 외의 객체 또는 클래스를 finalize하기 위한 처리의 결과 그렇게 되었을 경우를 제외합니다. finalize 메소드는, 이 객체를 다른 thread로 다시 이용 가능하게 하는 일도 포함해, 임의의 액션을 실시할 수가 있습니다. 그러나,finalize 의 일반적으로의 용도는, 객체를 재생 불가능한 형태로 파기하기 전의 클린 업을 실행하는 것입니다. 예를 들어, 입출력의 접속을 나타내는 객체의 finalize 메소드는, 객체가 영구적으로 파기되기 전에, 접속을 절단하기 위한 명시적인 입출력 처리를 실시합니다. 

Object 클래스의 finalize 메소드는, 특별한 처리를 실시하지 않습니다. 일반적으로은, 아무것도 하지 않고 복귀합니다. Object 의 서브 클래스는, 이 정의를 오버라이드(override) 할 수가 있습니다. 

Java 프로그램 언어는, 임의의 객체에 대해 어느 thread가 finalize 메소드를 호출하는지를 보증하지 않습니다. 그러나, finalize 를 호출하는 thread가, 사용자에게 가시인 동기 락을 finalize 호출의 시점에서는 보관 유지하고 있지 않는 것에 붙어 보증됩니다. 캐치 되지 않는 예외를 finalize 메소드가 throw 했을 경우, 예외는 무시되어 객체의 finalize는 종료합니다. 

어느 객체에 대해 finalize 메소드가 불려 간 뒤에 다음의 처리가 발생하는 것은, 아직 생존하고 있는 임의의 thread가 이 객체에 액세스 할 수 있는 방법은 없으면 Java 가상 머신이 다시 판단했을 때입니다. 이것에는, finalize의 준비가 되어 있는 것 외의 객체 또는 클래스에 의해 발생한 처리도 포함되어 그 시점에서 이 객체는 파기됩니다. 

임의의 객체에 대해 Java 가상 머신이 finalize 메소드를 여러 차례 호출할 것은 없습니다.  finalize 메소드에 의해 예외가 throw 되면(자),finalize 메소드의 처리는 정지됩니다. 그렇지 않은 경우는 무시됩니다.

예외:
Throwable - 이 메소드로 생긴 Exception

Minor GC
New/Young 영역의 GC를 Minor GC라 부른다.
New/Young 영역은 다시 Eden과 Survivor 영역으로 나뉜다.

Eden 영역 : Java 객체가 생성되자 마자 저장되는 곳으로 이렇게 생성된 객체는 Minor GC가 발생할 때 Survivor영역으로 이동된다.
Survivor 영역 : Survivor1, Suvivor2 영역으로 나뉘며 Minor GC가 발생하면 Eden과 Survivor1에 있는 객체를 Survivor2로 복사한다. 그리고 Alive 되어 있지 않은 객체는 자연히 Survivor1에 남겨지고 Survivor1과 Eden 영역을 Clear한다.
이런 방법을 Copy & Scavenge 방식이라 하며 속도가 빠르고 작은 크기의 메모리를 Collecting하는데 효과적이다. Minor GC의 경우 자주 일어나기 때문에 GC에 소요되는 시간이 짧은 알고리즘에 적합(보통 0.5초 이내에 끝남)
Full GC
Old 영역의 GC를 Full GC라 부르며 사용되는 알고리즘으로는 Mark & Compact을 사용한다.
전체 객체의 Reference를 따라가면서 reference가 연결되지 않은 객체를 Mark한다.
이 작업이 끝나면 사용되지 않는 객체들은(Mark된 객체) 삭제된다.
특징 : 속도가 느리며 Full GC가 일어나는 도중 순간적으로 Java Application이 멈추기 때문에 Full GC가 일어나는 정도와 Full GC에 소요되는 시간은 Application의 성능과 안정성에 아주 큰 영향을 준다.(보통 수초가 걸린다.)


JVM의 일반적인 GC 알고리즘
- Default Collector
- Parallel GC for young generation (from JDK 1.4 )
- Concurrent GC for old generation (from JDK 1.4)
- Incremental GC (Train GC)

Defalut Collectior
전통적인 Minor GC에 Scavenge를 Full GC에 Mark & Compact 알고리즘을 사용하는 방법

Parallel GC
4cpu의 256 정도의 메모리를 가지고 있는 HW에서 유용하게 사용된다.
(1cpu에서는 동시에 여러개의 thread를 실행할 수 없기 때문에 오히려 parallel GC가 Default GC에 비해 느림)

Concurrent GC
Full GC, 즉 Old 영역을 GC하는 경우 그 시간이 길고 Application이 순간적으로 멈추기 때문에 시스템 운용에 문제가 된다.
그래서 이런 Full GC의 단점을 보완하기 위해 멈추는 현상을 최소화 하는 방법
일부는 Application이 돌아가는 단계에서 수행하고 최소한의 작업만을 Applicaton이 멈췄을때 수행하는 방법으로 Application이 멈추는 시간을 최소화한다.

Incremental GC(Train GC)
Concurent GC와 비슷하며 의도자체는 Full GC에 의해서 Application이 멈추는 시간을 줄이고자 하는데 있다.
동작 원리는 Minor GC가 일어날 때 마다 Old 영역을 조금씩 GC하여 Full GC가 발생하는 횟수나 시간을 줄이는 방법이다.
하지만 Incremental GC는 많은 자원을 소모하고 Minor GC를 자주 일으키고 Full GC가 없어진다거나 획기적으로 줄어드는 것은 아니다. 오히려 느려지는 경우가 있으니 반드시 실환경에 맞게 테스트를 해야한다.

 

'Study > Programming' 카테고리의 다른 글

자바 AWT 10진수 16진수 변환기  (0) 2010.02.16
자바 형변환  (0) 2010.02.11
플렉스 채팅 프로그램  (0) 2009.08.14
이클립스 FLEX 프로젝트 생성방법  (0) 2009.08.10
JSP 게시판 만들기  (2) 2009.07.27