티스토리 뷰

Java

Garbage Collector

LichKing 2017. 7. 5. 23:22

자바를 처음 공부할때 각종 자바의 장점들에 대해 배우는데 그 중 하나는 자바는 메모리 관리를 할 필요가 없다 라는 것이다. 그 이유는 GC때문인데, 'GC가 관리해주니 메모리를 관리할 필요가 없다' 라는것만 배우고 GC에 대해서는 이해도가 높지않은 경우가 많다. 하지만 GC에 대해서도 어느정도는 알고있어야 내 코드에서 성능 문제가 발생했을때 트러블슈팅을 할 수 있을것이다. GC에 대해 간략하게 정리해본다.


1. JVM 메모리구조



JVM 메모리구조를 간략히 도식화한 것이다. 

static 영역은 정적으로 로딩되는 데이터들이 들어가게되고 JVM의 모든 스레드들이 공유하게된다.


stack 영역은 스레드별로 할당되는 영역이다. 쉽게말해 메서드의 지역변수들이 stack에 선언된다고 보면된다. 스레드별로 할당되기때문에 지역변수는 멀티스레드에 안전하다. 보통 메서드를 재귀적으로 호출하다보면 stackoverflowerror 가 발생하게되는데 그때나오는 stack이 바로 이 stack이다.


heap 영역이 동적으로 메모리가 할당/회수 되는 영역이다. 객체를 생성할때 생성되는 객체가 heap에 할당된다. 마찬가지로 참조가 끊긴 객체들이 GC발생시 회수되게된다. GC가 발생하는 영역은 바로 이 heap 영역이다.


1-1. Heap 메모리 구조



위 그림에서는 heap이 매우 단순하게 표현됐지만 heap도 더 세분화시킬 수 있다(이것도 간략하게 표현한 것이다.). 간단히 두개로 나누면 Young, Old로 구분할 수 있으며, 물론 그 각각의 구분들도 또다시 나눌 수 있다. 기본적으로 heap 영역의 메모리 할당은 eden 영역에서부터 차례대로 할당되게되며 각 영역에서 GC가 발생되게된다. 예를들어 eden 영역에 생성된 객체가 금방 쓰이고 참조가 끊기게되면 eden 영역에서 바로 소멸될 수도있고, eden에서 잘 버티면 추후에 survivor 영역으로 이동하고, 그 이후엔 old영역에까지 이동되게되는 셈이다. Young 영역에서 발생하는 GC는 Young GC 혹은 Minor GC 라고 부르며, Old 영역에서 발생하는 GC는 Old GC, Major GC 라고 부른다.


2. Garbage Collector

지금까지 아주 간단하게 JVM의 메모리 구조에 대해 알아봤다. 이제 GC의 종류에 대해 알아보자. GC의 종류는 많지만 크게크게 다르다기보단 한단계식 발전해나가는 방식이라 생각보다 크게 알아야할게 많거나 하지는 않은게 그나마 다행이다.


2-1. Serial GC

Serial이라는 명칭에 알맞게 순차적으로 실행되며 가장 단순한 알고리즘으로 실행된다.


* 객체가 생성되면 eden 영역에 저장

* 지속적으로 eden에 객체를 생성하다가 가득 차면 Minor GC(Young GC) 발생

* 쓰레기 객체들은 제거되고 아직 살아있는 객체들은 survivor 영역으로 이동

* 반복되다가 survivor 마저 꽉 차면 old 영역으로 이동


이것이 Serial GC의 Minor CG 실행 알고리즘이다.


Major CG(Old CG)는 Mark Sweep Compact 라는 알고리즘으로 실행되는데


* Mark : Old 영역에서 살아있는 객체를 식별

* Sweep : Old 영역에서 쓰레기 객체들을 식별

* Compact : 쓰레기 객체들을 수거하고 살아있는 객체들을 한곳에 모음


이런식으로 실행되게 된다. Serial GC의 가장 큰 단점은 GC 발생시 JVM이 완전히 멈춘다는 것이다.


2-2. Parallel GC

Serial GC와 동일한 알고리즘으로 Minor GC, Major GC를 수행하게 된다. 다만 병렬적으로 수행하기때문에 CPU가 대기상태로 있는것을 최소화 한다.


2-3. Parallel Compact GC

Minor GC는 Parallel GC와 동일하게 작동한다. Major GC에 차이가 있는데


* Mark : Old 영역에서 살아있는 객체를 식별

* Summary : 이전 GC에서 살아남아 모여있는 객체의 위치를 조사

* Compact : 쓰레기 객체들을 수거하고 살아있는 객체들을 한곳에 모음


이런 차이가 있다. 사실 앞선 Mark Sweep Compact 알고리즘과 무슨 차이인지 알기 힘들것이다. 2번째 부분이 다른데 Parallel Compact GC는 이전에 실행한 영역을 따로 훑는다는 차이가 있다. 음.. 아직 이부분은 나도 잘 이해가 안된다.


2-4. Concurrent Mark Sweep GC

Young GC 는 Parallel GC 와 동일하고, Major GC에서 차이를 보인다.


* 초기 표시 단계 : 빠르게 살아있는 객체를 찾음

* 컨커런트 표시 단계 : JVM이 멈추지 않은 상태에서 살아있는 객체에 표시

* 재표시 단계 : 컨커런트 표시 단계에서 표시하는 동안 변경된 객체에 대해서 재표시

* 컨커런트 스윕 단계 : 표시되어 있는 쓰레기 객체를 수거


Concurrent Mark Sweep GC는 Compact 단계가 없다. 때문에 메모리 중간중간에 빈공간이 발생하게된다.


2-5. Garbage First GC

First를 숫자 1로 치환하여 G1GC라고도 표현한다. G1GC의 경우는 여태 알아본 GC들과는 상당히 다른 방식으로 작동하며, 일단 앞서 알아봤던 메모리 구조부터가 다르다.

앞선 GC들은 Heap 영역을 각각의 용도로 구분하여 사용하였지만 G1GC는 각각의 용도를 구분짓지 않는다. 구분짓지 않는다기보다는 상당히 유기적으로 구분짓는다.


* Heap 영역에서 일부구역을 Young 영역으로 지정

* Young 영역에 객체가 생성되고, Young 영역이 가득차면 Minor GC를 발생시킨다.

* 마찬가지로 끝까지 살아남은 객체들은 Old 영역으로 이동한다.


Major GC는 아래와 같이 실행된다.

* 초기 표시 단계 : Old 영역에 있는 객체에서 Survivor 영역의 객체를 참조하고 있는 객체 표시

* 기본 구역 스캔 단계 : Old 영역 참조를 위해 Survivor 영역 탐색(Young GC 발생 이전)

* 컨커런트 표시 단계 : 전체 Heap 영역에 살아있는 객체 탐색

* 재표시 단계 : heap에 살아있는 객체 표시

* 청소 단계 : 쓰레기 객체들을 수거한다. 빈 공간을 초기화한다.

* 복사 단계 : 살아있는 객체들을 빈 공간으로 모은다.


참고문헌

스프링 입문을 위한 자바 객체지향의 원리와 이해

자바 성능 튜닝 이야기

'Java' 카테고리의 다른 글

DDD#01. Domain Object  (1) 2017.07.23
다형성 연습하기  (0) 2017.07.08
DTO와 VO  (8) 2017.07.01
jackson custom serializer, deserializer 만들기  (3) 2017.04.19
Java8#06. time package  (1) 2017.03.04
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함