시작에 앞서..

java GC 를 다루게 된 것은 별다른 이유가 있는 것은 아닙니다. java 개발을 하고 있고 언젠가 봐야지 하며 미루던 것을 하나씩 정리 하려고 합니다. 앞으로도 java 또는 개발에 필요한 기초를 하나씩 점검해 보고자 합니다.

Hello World? Stop the World!

  • GC 를 실행하기 위해 JVM 이 어플리케이션 실행을 멈추는 것.
  • stop-the-world 가 발생하면 GC 를 실행하는 쓰레드를 제외한 나머지 쓰레드는 모두 작업을 멈춤
  • GC 를 튜닝 한다는 것은 “stop-the-world” 의 시간을 줄이는 것.

객체와 Garbage Collection

  1. Created (생성)
    • 객체를 Heap 에 할당
    • Super Class 의 생성자 호출
    • initialize 수행 및 객체의 생성자 호출
  2. In use or reachable (사용중)
    • 객체가 생성되어 다른 객체에 의해 참조 중인 상태 (Strongly referenced)
  3. Invisible (사용 중 but 접근 불가)
    • 특정 클래스에서 객체로 생성되어 Strongly referenced 상태이나 다시 접근할 수 없는 상태
    • 이때 명시적으로 Unreachable 상태로 바꿔주는것이 좋다.
  4. Unreachable (사용 되지 않음)
    • 이 상태는 GC 의 후보가 되어 GC 대상 큐에 들어 감.
    • 실제 GC 가 발생할때 해당 큐의 내용을 메모리 해제
  5. Collected (GC 대상)
    • GC 가 해당 객체의 finalize() 가 정의 되어있는지 판단하고 있다면 finalizer 큐에 넣는다.
    • 만약 없다면 finalized 상태로 전환 시킨다.
  6. Finalized (Finalize 를 거친 상태)
    • Finalizer에 의해 finalize가 실행된 후의 상태
    • JVM(자바가상머신)에 따라서 수행 시간도 다르다.
  7. Deallocated (메모리 해제 된 상태)
    • 메모리 변환 완료, GC 끝

GC? 조금 더 자세히 보자

  • 대부분의 객체는 금방 접근 불가능 상태(unreachable) 가 된다.
  • 오래된 객체에서 젊은 객체로의 참조는 아주 적다.
  • Young Generation:
    1. 새롭게 생성한 객체의 대부분이 여기에 위치한다.
    2. 대부분의 객체가 금방 접근 불가능 상태가 되기 때문에 매우 많은 객체가 Young 영역에 생성 되었다가 사라진다. (bump-the-pointer, TLABs)
    3. 이 영역에서 객체가 사라질 때 Minor GC 가 발생 한다고 말한다.
    4. Eden, Survivor1,2 영역에서 GC 가 발생하고 Old 영역으로 이동
  • Old Generation:
    1. 접근 불가능 상태 분류되 Young 영역에서 살아남은 객체가 여기로 복사된다.
    2. 대부분 Young 영역보다 크게 할당한다.
    3. 크기가 큰 만큼 Young 영역보다 GC 발생 빈도는 적다.
    4. 이 영역에서 객체가 사라질 때 Major GC(혹은 Full GC)가 발생한다고 말한다

출처: https://d2.naver.com/helloworld

출처: http://blog.skby.net

  • MAJOR GC 의 종류
    1. Serial GC
    2. Parallel GC
    3. Parallel Old GC(Parallel Compacting GC)
    4. Concurrent Mark & Sweep GC(이하 CMS)
    5. G1(Garbage First) GC

GC 의 발생을 결정짓는 중요 포인트… GC 의 중요성

  • Strong Reference 의 유지 여부가 포인트
  • 만약 잘못된 개발로 인해 memory full 이 발생하면?
    1. 가상메모리 사용
      • Ram 과 HDD 사이에 memory swap 은 성능 저하를 유발 한다.
    2. Out of Memory Error 발생
      • 제대로 된 예외처리 없이는 application 이 다운되는 상황까지 가게 된다.
      • android 의 경우 메모리 확보를 위해 중요도가 낮은 프로세스를 강제로 kill 함.
    3. 미숙한 메모리 관리 > 지속적인 GC 유발
      • 엄청난 성능 하락의 원인이 된다.

GC 를 강제로 호출하는 것은 가능 할까?

  • System.gc(), Runtime.getRuntiem().gc()
  • GC의 소모 리소스의 양이 많다
  • 잘못 된 사용으로 성능이 저하된 application 이 만들어지기 쉽다.

마치며

서비스의 상황에 따라 사용하는 WAS 환경과 장비가 모두 다르기 때문에 WAS 를 서비스에 맞춰 설정하듯 GC 의 옵션, 튜닝은 서비스 성능에 도움을 줄 수 있다. 다만 정확하게 알고 적용해야 하며 함부로 GC 함수를 호출해서는 안된다.

java7 과 java8 의 아키텍쳐 변화

  • java7 eden / survive / old / perm
  • java8 eden / survive / old / metaspace

reference

ryan's profile image

ryan

2019-08-25 10:00

ryan 님이 작성하신 글 더 보기