가비지 컬렉션(Garbage Collection)
당연하게 생각하고 써왔지만 컴팩트한 개발에 꼭 필요한 가비지 컬렉션 이해
가비지 컬렉션이란?
- 가비지 컬렉션은 영어로 Garbage Collection, 줄여서 GC라고도 부른다.
가비지 컬렉션은 자바의 메모리 관리 방법 중의 하나로 JVM Heap 영역에서 동적으로 할당했던 메모리 영역 중 필요 없게 된 메모리 영역을 주기적으로 삭제하는 프로세스를 말한다.
c나 c++에서는 가비지 컬렉션이 없어 개발자가 수동으로 메모리 할당과 해제를 일일이 해줘야 하는 반면 Java는 JVM에 탑재되어 있는 가비지 컬렉터가 메모리 관리를 대행해주기 때문에 개발자 입장에서 메모리 관리, 메모리 누수(Memory Leak) 문제에 대해 완벽하게 관리하지 않아도 되어 오롯이 개발에만 집중할 수 있다는 장점이 있다.
가비지 컬렉션의 유의점
- 개발자가 메모리가 언제 해제되는지 정확하게 알 수 없다.
- 가비지 컬렉션이 동작하는 동안에는 다른 동작을 멈추기 때문에 오버헤드가 발생한다.
- 가비지 컬렉션에는 장점만 있는 것이 아니라 단점도 존재한다. 대표적으로 위의 2가지 단점이 있다.
이 중에서 2번 GC가 동작하는 동안 JVM의 다른 동작들은 잠깐 멈추기 때문에 오버헤드가 발생한다는 점을 특히 주의해야 한다.
이로 인해 GC가 너무 자주 실행되면 소프트웨어 성능 하락의 문제가 되기도 한다. 이러한 특성으로 인해 실시간으로 계속 동작해주어야 하는 시스템들은 GC의 사용이 적합하지 않을 수 있다. - 오버헤드란?
- 오버헤드는 어떤 처리를 하기 위해 들어가는 간접적인 처리 시간, 메모리 등을 말한다.
예를 들어, A라는 처리를 실행하는데 10초가 걸린다고 가정했을 때 부가적인 B라는 처리를 추가한 결과 처리시간이 15초가 걸렸다면, 오버헤드는 5초가 된다.
가비지 컬렉션의 대상
- 객체들은 실질적으로 Heap 영역에 생성되고 Method 영역이나 Stack 영역 등 root 영역에서 Heap 영역에 생성된 객체의 주소만 참조하는 형식으로 구성된다.
하지만 이렇게 생성된 Heap 영역의 객체들이 메서드가 끝나는 등의 특정 이벤트들로 인하여 Heap 영역 객체의 메모리 주소를 가지고 있는 참조 변수가 삭제되는 현상이 발생하면,
Heap 영역에서 어디서든 참조하고 있지 않은 객체들이 발생하게 된다.
이러한 객체들을 Unreachable(닿을수 없는) 하다고 하며 주기적으로 가비지 컬렉터가 제거해준다. - Unreachable, Reachable?
- Reachable: 객체가 참조되고 있는 상태
- Unreachable: 객체가 참조되고 있지 않은 상태(GC의 대상이 됨)
Mark And Sweep 알고리즘
- Mark And Sweep 알고리즘은 가비지 컬렉션이 동작하는 원리로 루트에서부터 해당 객체에 접근 가능한지에 대한 여부를 메모리 해제의 기준으로 잡습니다.
Mark And Sweep은 아래의 3가지 과정으로 이루어 집니다.
- Mark 과정: 먼저 Root로부터 그래프 순회를 통해 연결된 객체들을 찾아내어 각각 어떤 객체를 참조하고 있는지 찾아서 마킹한다. (탐색)
- Sweep 과정: 참조하고 있지 않은 객체 즉 Unreachable 객체들을 Heap에서 제거한다. (삭제)
- Compact 과정: Sweep 후에 분산된 객체들을 Heap의 시작 주소로 모아 메모리가 할당된 부분과 그렇지 않은 부분으로 압축한다. (가비지 컬렉터 종류에 따라 하지 않는 경우도 있음) (정리)
가비지 컬렉션 동작 과정
- 객체가 처음 생성되고 Heap영역의 Eden에 age-bit 0으로 할당된다. 이 age-bit는 Minor GC에서 살아남을 때마다 1씩 증가하게 된다.
- 시간이 지나 Heap Area의 Eden 영역에 객체가 다 쌓이게 되면 Minor GC가 한번 일어나게 되고 참조 정도에 따라 Servivar0 영역으로 이동하거나 회수한다.
- 계속해서 Eden 영역에는 신규 객체들이 생성된다. 이렇게 또 Eden 영역에 객체가 다 쌓이게 되면 Young Generation(Eden + Servivor) 영역에 있는 객체들을 비어있는 Survival인 Survival1 영역에 이동하고 살아남은 모든 객체들은 age가 1씩 증가한다.
- 또 다시 Eden 영역에 신규 객체들로 가득 차게 되면 다시한번 Minor GC가 일어나고 Young Generation(Eden + Servival) 영역에 있는 객체들을 비어있는 Survival인 Survival0으로 이동시킨 뒤 age를 1 증가시킨다. 이 3~4 의 과정을 계속해서 반복하게 된다.
- 이 과정을 반복하다 보면 age bit가 특정 숫자 이상으로 되는 경우가 발생한다. 이 때 JVM에서 설정해놓은 age bit에 도달하게 되면 오랫동안 쓰일 객체라고 판단하고 Old generation 영역으로 이동시킨다. 이 과정을 프로모션(Promotion) 이라고 한다.
- 시간이 지나 Old영역에 할당된 메모리가 허용치를 넘게 되면, Old 영역에 있는 모든 객체들을 검사하여 참조되지 않는 객체들을 한꺼번에 삭제하는 GC가 실행된다. 이렇게 Old generation 영역의 메모리를 회수하는 GC를 Major GC라고 한다. Major GC는 시간이 오래 걸리는 작업이고 이 때 GC를 실행하는 스레드를 제외한 모든 스레드는 작업을 멈추게 된다. 이를 'Stop-the-World' 라고 한다. 이 작업이 너무 잦으면 프로그램 성능에 문제가 될 수 있다.
추가해서 정리할 주제
- 가비지 콜렉터의 종류
정리 및 소감
가비지 컬렉션에 대해서 막연하게만 알고 있었는데, 좀 더 상세히 공부를 해보니 앞으로 개발을 할 때 더 퀄리티 높은 개발을 할 수 있을 것 같다! 어떻게 동작하는지 동작원리를 알고 개발하는 것과 모르고 개발하는 것은 정말 천지 차이니까 ^^
'Language > Java' 카테고리의 다른 글
인터페이스와 추상클래스 (0) | 2024.07.16 |
---|---|
서블릿(Servlet) (1) | 2024.07.16 |
예외(Exception) 처리 (3) | 2024.07.16 |
스트링(string) (0) | 2024.07.16 |
자바(JAVA) 빌더(builder) 패턴 (0) | 2023.01.05 |
가비지 컬렉션(Garbage Collection)
당연하게 생각하고 써왔지만 컴팩트한 개발에 꼭 필요한 가비지 컬렉션 이해
가비지 컬렉션이란?
- 가비지 컬렉션은 영어로 Garbage Collection, 줄여서 GC라고도 부른다.
가비지 컬렉션은 자바의 메모리 관리 방법 중의 하나로 JVM Heap 영역에서 동적으로 할당했던 메모리 영역 중 필요 없게 된 메모리 영역을 주기적으로 삭제하는 프로세스를 말한다.
c나 c++에서는 가비지 컬렉션이 없어 개발자가 수동으로 메모리 할당과 해제를 일일이 해줘야 하는 반면 Java는 JVM에 탑재되어 있는 가비지 컬렉터가 메모리 관리를 대행해주기 때문에 개발자 입장에서 메모리 관리, 메모리 누수(Memory Leak) 문제에 대해 완벽하게 관리하지 않아도 되어 오롯이 개발에만 집중할 수 있다는 장점이 있다.
가비지 컬렉션의 유의점
- 개발자가 메모리가 언제 해제되는지 정확하게 알 수 없다.
- 가비지 컬렉션이 동작하는 동안에는 다른 동작을 멈추기 때문에 오버헤드가 발생한다.
- 가비지 컬렉션에는 장점만 있는 것이 아니라 단점도 존재한다. 대표적으로 위의 2가지 단점이 있다.
이 중에서 2번 GC가 동작하는 동안 JVM의 다른 동작들은 잠깐 멈추기 때문에 오버헤드가 발생한다는 점을 특히 주의해야 한다.
이로 인해 GC가 너무 자주 실행되면 소프트웨어 성능 하락의 문제가 되기도 한다. 이러한 특성으로 인해 실시간으로 계속 동작해주어야 하는 시스템들은 GC의 사용이 적합하지 않을 수 있다. - 오버헤드란?
- 오버헤드는 어떤 처리를 하기 위해 들어가는 간접적인 처리 시간, 메모리 등을 말한다.
예를 들어, A라는 처리를 실행하는데 10초가 걸린다고 가정했을 때 부가적인 B라는 처리를 추가한 결과 처리시간이 15초가 걸렸다면, 오버헤드는 5초가 된다.
가비지 컬렉션의 대상
- 객체들은 실질적으로 Heap 영역에 생성되고 Method 영역이나 Stack 영역 등 root 영역에서 Heap 영역에 생성된 객체의 주소만 참조하는 형식으로 구성된다.
하지만 이렇게 생성된 Heap 영역의 객체들이 메서드가 끝나는 등의 특정 이벤트들로 인하여 Heap 영역 객체의 메모리 주소를 가지고 있는 참조 변수가 삭제되는 현상이 발생하면,
Heap 영역에서 어디서든 참조하고 있지 않은 객체들이 발생하게 된다.
이러한 객체들을 Unreachable(닿을수 없는) 하다고 하며 주기적으로 가비지 컬렉터가 제거해준다. - Unreachable, Reachable?
- Reachable: 객체가 참조되고 있는 상태
- Unreachable: 객체가 참조되고 있지 않은 상태(GC의 대상이 됨)
Mark And Sweep 알고리즘
- Mark And Sweep 알고리즘은 가비지 컬렉션이 동작하는 원리로 루트에서부터 해당 객체에 접근 가능한지에 대한 여부를 메모리 해제의 기준으로 잡습니다.
Mark And Sweep은 아래의 3가지 과정으로 이루어 집니다.
- Mark 과정: 먼저 Root로부터 그래프 순회를 통해 연결된 객체들을 찾아내어 각각 어떤 객체를 참조하고 있는지 찾아서 마킹한다. (탐색)
- Sweep 과정: 참조하고 있지 않은 객체 즉 Unreachable 객체들을 Heap에서 제거한다. (삭제)
- Compact 과정: Sweep 후에 분산된 객체들을 Heap의 시작 주소로 모아 메모리가 할당된 부분과 그렇지 않은 부분으로 압축한다. (가비지 컬렉터 종류에 따라 하지 않는 경우도 있음) (정리)
가비지 컬렉션 동작 과정
- 객체가 처음 생성되고 Heap영역의 Eden에 age-bit 0으로 할당된다. 이 age-bit는 Minor GC에서 살아남을 때마다 1씩 증가하게 된다.
- 시간이 지나 Heap Area의 Eden 영역에 객체가 다 쌓이게 되면 Minor GC가 한번 일어나게 되고 참조 정도에 따라 Servivar0 영역으로 이동하거나 회수한다.
- 계속해서 Eden 영역에는 신규 객체들이 생성된다. 이렇게 또 Eden 영역에 객체가 다 쌓이게 되면 Young Generation(Eden + Servivor) 영역에 있는 객체들을 비어있는 Survival인 Survival1 영역에 이동하고 살아남은 모든 객체들은 age가 1씩 증가한다.
- 또 다시 Eden 영역에 신규 객체들로 가득 차게 되면 다시한번 Minor GC가 일어나고 Young Generation(Eden + Servival) 영역에 있는 객체들을 비어있는 Survival인 Survival0으로 이동시킨 뒤 age를 1 증가시킨다. 이 3~4 의 과정을 계속해서 반복하게 된다.
- 이 과정을 반복하다 보면 age bit가 특정 숫자 이상으로 되는 경우가 발생한다. 이 때 JVM에서 설정해놓은 age bit에 도달하게 되면 오랫동안 쓰일 객체라고 판단하고 Old generation 영역으로 이동시킨다. 이 과정을 프로모션(Promotion) 이라고 한다.
- 시간이 지나 Old영역에 할당된 메모리가 허용치를 넘게 되면, Old 영역에 있는 모든 객체들을 검사하여 참조되지 않는 객체들을 한꺼번에 삭제하는 GC가 실행된다. 이렇게 Old generation 영역의 메모리를 회수하는 GC를 Major GC라고 한다. Major GC는 시간이 오래 걸리는 작업이고 이 때 GC를 실행하는 스레드를 제외한 모든 스레드는 작업을 멈추게 된다. 이를 'Stop-the-World' 라고 한다. 이 작업이 너무 잦으면 프로그램 성능에 문제가 될 수 있다.
추가해서 정리할 주제
- 가비지 콜렉터의 종류
정리 및 소감
가비지 컬렉션에 대해서 막연하게만 알고 있었는데, 좀 더 상세히 공부를 해보니 앞으로 개발을 할 때 더 퀄리티 높은 개발을 할 수 있을 것 같다! 어떻게 동작하는지 동작원리를 알고 개발하는 것과 모르고 개발하는 것은 정말 천지 차이니까 ^^
'Language > Java' 카테고리의 다른 글
인터페이스와 추상클래스 (0) | 2024.07.16 |
---|---|
서블릿(Servlet) (1) | 2024.07.16 |
예외(Exception) 처리 (3) | 2024.07.16 |
스트링(string) (0) | 2024.07.16 |
자바(JAVA) 빌더(builder) 패턴 (0) | 2023.01.05 |