ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java GC(Garbage Collection) 동작 방식
    카테고리 없음 2016. 11. 25. 20:25



    Java 관련 코드를 정리하는중 IO와 관련한 클래스 인스턴스들의 close() 호출처리를 개선하게 되었다. 그러다 문득, IO관련된 인스턴스들은 Resource leak 때문에 close를 반드시 호출해야 한다고 알고 있었는데, 그러면 close되지 않은 즉, 메모리에 올려진 인스턴스들을 처리하는 Java GC(Garbage Collection)이라는 것은 어떻게 동작하는지 궁금해 구글링을 통해 자료들을 정리하여 보았다.


    Java에서 명명하는 memory leak 에 대한 명쾌한 설명




    Garbage Collection 특징


    ( 이하 GC로 표기 )

    1) 객체들은 힙에 생성된다.
    2) GC는 GC 대상이 되는 객체들을 힙에서 제거하기 위해 JVM에서 제공되는 매커니즘이다. 
    3) GC는 C++처럼 별도의 메모리 관리를 할 필요가 없으며 비즈니스 로직에 집중할 수 있게 해준다.
    4) GC는 Garbage Collector 라고 불리는 데몬 스레드에 의해 수행된다.
    5) 객체를 메모리에서 제거하기 전에 Garbage Collector 스레드는 해당 객체의 finalize() 메소드를 호출한다.
    6) GC를 강제로 수행할 수는 없다. JVM이 힙 사이즈에 기반해서 GC가 필요한 경우에만 수행된다. 
    7) GC 요청을 보내기 위한 System.gc(), Runtime.gc()가 있지만 GC를 보장하지 않는다.
    8) 힙에 새로운 객체를 생성할 메모리가 없다면 JVM은 OOM(Out Of Memory Error)를 던진다.


    객체는 언제 GC 대상이 되나?


    객체는 살아있는 Thread나 static 참조를 통해 도달할 수 없게 된다면 GC 대상이 된다. 다시말해 모든 객체의 참조가 모두 null일 경우에 GC 대상이 된다. 객체 A가 B를 참조하고, 객체 B가 A를 참조하는 원형참조일 경우 참조로 간주하지 않는다. 객체 A,B에 다른 살아있는 객체의 참조가 없다면 GC 대상이 된다.


    일반적으로 다음과 같은 경우 GC의 대상이 된다.

    1) 모든 객체 참조가 null인 경우 (e.g object = null)

    2) 객체가 블럭 안에서 생성되고 블럭이 종료되었을 경우

    3) 부모 객체가 null이 되었을 경우, 자식 또는 포함된 객체들은 자동적으로 GC 대상이 된다.

    4) 객체가 WeakHashMap의 참조만 가지고 있을 경우





    객체는 힙에 생성된다. 힙은 Young, Tenured(=Old), Permanent(=Perm Area) Generation의 세 영역으로 나뉜다. 또 Young Generation은 Eden, Survivor1, Survivor2 영역으로 나뉜다. 객체는 처음 생성될 때 Young Generation의 Eden 영역에서 생성된다. Minor GC 이후 객체가 살아 있다면 Survivor1으로 옮겨진다. Major GC 전에 Survivor2의 객체는 Tenured Generation으로 옮겨진다. Permanent Generation은 클래스나 메소드 등의 메타데이터를 저장하거나 String Pool의 공간으로 사용되어지는 조금 특별한 공간이다. Permanent Generation에서 GC가 수행되는지에 대한 많은 의견이 있지만 내 지식으로는 JVM 벤더에 의존적이다. Sun에서 구현한 JVM에서는 적어도 GC가 수행된다. 



    Garbage Collector 유형 (Garbage Collection과 다름)

    Java5에서는 다양한 Garbage Collector를 제공한다. Serial Garbage Collector를 제외하고 3가지 Collector가 추가되었다. 각 Grabage Collector는 어플리케이션의 Throughput을 증가시키거나 GC하는 동안 어플리케이션이 멈추는 시간을 감소시키기 위해 구현되었다.




    GC 관련 JVM 파라미터 설정


    GC 튜닝을 제대로 하려면 많은 경험과 어플리케이션 프로파일링 그리고 인내심이 필요하다. 프로젝트에서 프로파일링, Full GC(=Major GC)의 원인을 찾음으로써 자바 어플리케이션의 성능을 증가시킬 필요가 있었는데, GC튜닝은 대게 처플리케이션 프로프일에 의존적이다. 처플리케이션에서 어떤 종류의 객체를 가지고 있는지, 평균 라이프타임은 얼마인지 등, 예를들어 어플리케이션이 짧게 사는 객체들들 많이 가지고 있다면 Eden 영역을 충분히 크게 만듦으로써 Minor GC 횟수를 감소시킬 수 있다. 또한 JVM 파라미터를 사용해서 Young과 Tenured Generation의 크기를 조절할 수 있다. 예를 들어 -XX:NewRatio=3으로 설정하면 Tenured:Young 영역이 1:3 비율의 크기로 생성된다. 하지만 이러한 크기 조절에는 항상 주의해야 한다. 

    Young Generation을 더 크게 만듦으로써 Tenured Generation의 크기는 줄어들 것이다. 그로 인해 Major GC가 더 자주 발생하며 그 시간동안 어플리케이션이 멈추는 시간이 발생할 것이다. 이것은 결국 Throughput을 감소시킨다. 파라미터 NewSize와 MaxNewSize는 Young Generation 크기를 설정하는데 사용된다. 이 설정을 똑같이 설정하면 Young Generation 영역을 고정시킨다. GC 튜닝을 하기 전에 자바의 GC에 대해 상세히 이해해야만 한다. 




    Full GC와 Concurrent GC


    Concurrent Garbage Collector는 어플리케이션 Thread와 병행적으로 수행되는 단일 Garbage Collector Thread를 사용한다. 이 Collector의 목적은 Tenured Generation이 Full 되기 전에 GC를 완료하는 것이다. 정상 동작할 경우 Concurrent Garbage Collector는 대부분 어플리케이션 Thread와 함께 수행된다. 그래서 단지 어플리케이션 쓰레드가 잠깐 멈춘것 처럼 보인다. 정상 동작하지 않을 경우의 대비책으로 만일 Concurrent Garbage Collector가 Tenured Generation이 가득차기 전에 GC를 긑마치지 못했다면 어플리케이션은 멈출 것이고 모든 어플리케이션 Thread가 정지하고나서 GC가 완료된 것이다. 어플리케이션이 중지되는 Full Garbage Collection 또는 Full GC라고 불리는 이러한 Collection은 Concurrent Collection Parameter를 조절할 필요가 있다는 신호이다. 또한 Full GC는 자바 어플리케이션 성능에 영향을 주기 때문에 최소화하거나 피하기 위해 항상 노력해야한다.




    요약


    1) 자바 힙은 Young, Tenured, Permanent Generation의 세 영역으로 구성되어 있다.

    2) 새로운 객체는 Young Generation에 생성되고 그 후에 Tenured Generation으로 이동한다.

    3) String Pool은 Perm Generation에 생성된다. Perm Generation은 GC는 일어나지만 JVM 벤더에 의존적이다.

    4) Minor GC 객체가 Eden 영역에서 Survivor1, Survivor2 영역으로 이동할 때 수행된다. Major GC는 객체가 Young에서 Tenured Generation으로 이동할 때 수행된다.

    5) Majog GC가 일어날 때마다 어플리케이션 Thread는 멈춘다.(Stop the world) 이는 어플리케이션의 성능과 Throughput을 감소시킨다.

    6) Java6에서는 GC에 많은 성능 향상이 있었다. JRE 1.6.20 이상을 써라.

    7) JVM 커맨드라인 옵션 -Xmx와 -Xms는 힙 크기의 시작과 최대 사이즈를 설정하는데 사용한다.

    8) 자바에서 GC를 수동으로 수행할 수 있는 방법은 없다.


    GC 튜닝에 대한 자료는 아래의 링크 참조





    [참고] 


Designed by Tistory.