본문 바로가기
Language/자바

자바 가비지 콜렉터(GC)에 대한 정리.

by 띵커베르 2023. 2. 12.
728x90
  • 이번에 자바 성능 튜닝 이야기 책을 읽으면서 기존에 알고있던 GC 에 대한것을 정리하려한다..
  • 너무 깊게 들어가면 끝이 안나고 이해도 어려워 이해하는 부분까지 정리..이미지도 첨부하면 더 이해가 빠르겠지만..넘어간다..(미래의 나에게 미안하다..ㅋㅋㅎ)
  • GC를 반드시 암기하고 숙지해야지 하는건 아니지만, 알고있으면 확실히 좋은듯 하다.

 

 

  • GC
    • C에서는 명시적으로 메모리를 건드리고 참조할 수 있다.
    • 자바에서는 메모리는 GC 라는 알고리즘을 통하여 관리하기 때문에, 개발자가 메모리를 처리하기 위한 로직을 만들 필요가 없고, 만들어서도 안된다.
    • JVM은 크게 3가지 영역으로 구성이된다
      • 클래스로더 
        • 바이트 코드를 읽고, 클래스 정보를 메모리의 메서드 영역에 저장
      • JVM Memory(런타임 데이터 영역)
        • 아래 설명
      • Execution Engine(실행 엔진)
        • 바이트 코드를 네이티브 코드로 변환해주고 GC를 실행
    • RunTime data area(런타임 데이터 영역) : 자바 프로그램이 실행되는 동안 필요한 메모리 공간을 정의
      • PC 레지스터
        • 쓰레드가 현재 실행할 스택 프레임의 주소를 저장하고 있다.
        • 자바의 스레드들은 각자의 pc(Program Counter) 레지스터를 갖는다.
        • 네이티브한 코드를 제외한 모든 자바 코드들이 수행될 때 JVM의 인스트럭션 주소를 pc 레지스터에 보관한다.
          • 인스트럭션 주소: JVM이 실행할 명령어의 주소 값
      • JVM 스택
        • 스레드가 시작할 때 JVM 스택이 생성된다.
        • 스택에는 메서드가 호출되는 정보인 프레임(frame)이 저아된다.
        • 로컬변수, 중간연산 결과, 메서드 수행과 리턴에 관련된 정보 등을 저장
      • 힙(Heap)
        • 아래 힙 메모리 영역 설명 참조.
      • 메서드 영역
        • 클래스 정의, 필드 정보, 메서드 정보 등 클래스 수준 정보를 포함하는 공유 메모리 영역이다.
        • JVM 을 시작할때 생성되며, JVM 내에서 실행 중인 모든 스레드에서 공유된다.
      • 네이티브 메서드 스택
        • 자바 코드가 아닌 다른 언어로 된(보통은 c)코드들이 실행하게 될 때의 스택 정보를 관리한다.
      • 자바의 메모리 영역은 Heap 메모리 와 Non-heap 메모리로 나뉜다.
        • heap 메모리 영역
          • Heap 자료구조를 구성하는 공간, 자바 프로그램에서 생성되는 모든 객체는 Heap 영역에 생성
          • 즉 프로그램이 실행 중 객체를 생성하고 관리하는 메모리 영역, GC 의 대상이다.
        • Non-heap 메모리 영역
          • Heap 영역과 달리 객체를 생성하거나 관리하는 것이 아닌 다른 용도로 사용되는 메모리 영역.
          • 자바 클래스 로더, 메서드 영역, 네이티브 메서드 스택, pc 레지스터 => GC 의 대상이 되지 않는다.
      • 위 영역중 GC 가 발생하는 부분은 힙(Heap) 영역이다.나머지는 GC 의 대상이 아니다.
    •  GC의 원리
      • GC는 다음의 역할을 한다
        • 메모리 할당
        • 사용 중인 메모리 인식
        • 사용하지 않는 메모리 인식
      • JVM의 Root Space
        • JVM의 GC 는 기본적으로 Mark-and-sweep 방식이다.
        • 이는 root 에서부터 해당 객체에 접근이 가능한지를 판단하여 수거대상의 기준이 된다.
          • 스택의 로컬 변수
          • 메서드 영역의 static 변수
          • 네이티브 메서드 스택의 JNI 참조
            • JNI 참조: 자바 프로그램에서 네이티브 언어(c, c++) 기반의 라이브러리 또는 시스템 호출을 할 수 있도록 하는 인터페이스에 관한 것이다.
            • JNI 참조는 자바 메서드에서 네이티브 메서드를 호출할 때 사용되는 메커니즘이다.
            • 네이티브 메서드 스택: JNI 호출 과정에서 자바 메서드와 네이티브 메서드 간에 데이터를 전달하는 데 사용되는 스택
        • Mark-and-sweep 방식의 특징
          • 의도적으로 GC 를 실행시켜야 한다.
          • 어플리케이션 실행과 GC 실행이 병행된다.
      • JVM 힙 영역은 Young, Old 영역으로 나뉜다.
        • Young 영역은 다시 Eden 영역 및 두 개의 Suvivor 영역으로 나뉜다.
        • Eden 영역이 꽉 차면 어디론가 옮겨지거나 삭제되어야 한다. 이 때 옮겨 가는 위치가 Suvivor 영역이다.
        • Suvivor1, Suvivor2 의 영역중 우선 순위가 있는 것은 아니고 두 개의 영역 중 한 영역은 반드시 비어 있어야 한다
        • Eden 영역에 있던 객체 중 GC 후 살아 남아 있는 객체들이 이동한다(이때 Age-bit 가 증가한다.)
        • Young 영역에서 발생하는 GC 를 마이너GC 라고 한다.
        • Old 영역에서 발생하는 GC 를 메이저GC 라고 한다.
        • 위의 작업이 반복되면서 일정수준의 Age-bit 를 넘어가면 Old 영역으로 옮겨지는데 이를 Promotion 이라 한다.
          • 자바 8에서는 Parallel GC 방식 사용 기준 age bit 15 가 되면 promotion이 진행됨
          • 자바 9에서 default 값인 G1 GC 의 age bit 는 정해져 있지 않다, 실행 중인 메모리 사용 패턴에 따라 가비지 수집 주기와 대상을 조정하는 것을 목적으로 하기 떄문이다.
        • Old 제네레이션 영역이 가득 찬다면 Mark-and-sweep 방식을 통해 필요 없는 메모리를 비우는데 이떄 Stop-The-World 가 발생한다.
        • 대부분의 객체의 생명주기는 짧고 새로 생성되는 객체가 저장되는데, 새로 생성된 객체는 많은 양의 메모리를 차지하지 않아 빠른 GC 속도로 처리할 수 있다. young 영역만 탐색하고, 해제하여 비용을 효율적으로 사용한다.
          • 새로 생성된 객체는 아직 그 기능이 전혀 사용되지 않았기 때문에, 그 객체가 필요한 메모리 양은 최소한으로 제한됩니다. 이러한 적은 메모리 양은 Young Generation에서 빠르게 GC 될 수 있습니다. 그러나, 객체의 생명 주기가 길어질수록 그 객체에 할당되는 메모리 양이 증가할 수 있습니다. 결국 객체의 생명 주기가 길어지면서 할당된 메모리 양이 증가하여 Old Generation으로 프로모션 될 수 있습니다.
        • Young 영역에서 Old 영역으로 넘어가는 객체 중 Suvivor 영역을 거치지 않고 바로 Old 영역으로 이동하는 객체가 있을 수 있다.
          • 객체의 크기가 아주 큰 경우: ex) Suvivor 영역의 크기가 16MB 인데 20MB를 점유하는 객체가 Eden 영역에서 생성되면 Suvivor 영역으로 옮겨갈 수가 없다.
      • G1 GC 에 대해..
728x90

댓글