본문 바로가기

Java/이론

GC(Garbage Collection) Re

결론적으로 개인적인 생각은 GC를 효율적으로 사용하면 개발시 메모리 관리를 간접적으로

설정할 수 있다! 즉 효율적이게 만드는데 아주 중요한 지식이라는 것이다.

 

정의 : 가비지 컬렉션(Garbage Collection, 이하 CG)은 자바의 메모리 관리 방법 중의 하나로 JVM(자바 가상

머신)의 Heap영역에서 동적으로 할당했던 메모리 중 필요 없게 된 메모리 객체(garbage)를 모아 주기적으로

제거하는 프로세스를 말한다.

Garbage Collector (Heep이 아니고 Heap...)

 

C/C++에서는 이러한 가비지 컬렉션이 없어 프로그래머가 수동으로 메모리 할당과 해제를 일일이 해줘야 했다.

→ C언어 때 배운 malloc()을 생각해보면 쉽게 알 수 있다. 장점은 사용자가 직접 메모리 관리를 하지 않아도

     CG라는 것이 있어서 개발에만 집중하면 되는것이다. 그러나 단점 또한 존재한다. 메모리가 언제 해제되는지

     개발자가 정확하게 알 수 없어 제어하기가 힘들다. 또한 다른 동작을 멈추기 때문에 오버헤드가 발생하는데

     이를 Stop-The-World라고 한다..

 

● STW(Stop The World)

GC를 수행하기 위해 JVM이 프로그램 실행을 멈추는 현상을 의미한다.

GC가 작동하는 동안 GC 관련 Thread를 제외한 모든 Thread는 멈추게 되어 서비스 이용해 차질이 생길 수 있다.

 

가비지 컬렉션 대상 선정

가비지 컬렉션은 특정 객체가 garbage인지 아닌지 판단하기 위해서 도달성, 도달능력(Reachability)이라는 개념을

적용한다. 객체에 레퍼런스가 있다면 Reachable로 구분되고, 객체에 유효한 레퍼런스가 없다면 unreachable로 구분해버리고 수거해버린다 (가비지 컬렉션은 JVM에서 이루어진다.)

JVM

 

위의 그림을 보면서 글을 읽으면 더욱 이해가 잘 될 것이다.

 

JVM메모리에서는 객체들은 실질적으로 Heap영역에서 생성되고 Method Area에서는 Heap Area에 생성된 객체의

주소만 참조하는 형식으로 구성된다.

빨간색 네모 박스 보면 어디에서도 참조되고 있지 않다. 저러한 Unreachable 메모리를 주기적으로 제거해주는 것이다.

그러면 청소를 어떻게 하느냐는 다음에 있다.

 

가비지 컬렉션 청소 방식

 

 

청소 방식은 위의 그림을 보면서 글을 읽으면 이해가 쉽게 될 것이다. 순서 자체는 심플하다. 

- 자바가 런타임을 시작하면 Root라는 것이 생기게 된다. 식별(Mark)하고 제거(Sweep)하고

  꽉 채운다(Compaction)

 

Heap 메모리 구조

GC(Carbage Collection)이 일어나는 Heap이라는 곳에서도 알아보자.

 

JVM 개발자들은 객체는 대부분 일회성이며, 메모리에 오랫동안 남아있는 경우는 드물다는 것을 기반으로

JVM을 개발했다. 이러한 특성을 이용해 Young과 Old 총 2가지 영역으로 설계하였다.

 

 

Young 영역(Young Generation)

● 새롭게 생성된 객체가 할당(Allocation)되는 영역

● 대부분의 객체가 금방 Unreachable 상태가 되기 때문에, 많은 객체가 Young 영역에 생성되었다가 사라진다.

● Young 영역에 대한 가비지 컬렉션을 Minor GC라고 부른다.

 

Old 영역(Old Generation)

Young영역에서 Reachable 상태를 유지하여 살아남은 객체가 복사되는 영역

● Young영역보다 크게 할당되며, 영역의 크기가 큰 만큼 가비지는 적게 발생한다.

● Old 영역에 대한 가비지 컬렉션(Garbage Collection)을 Major GC 또는 Full GC라고 부른다.

 

 

위에서 대략적인 Young영역과 Old영역을 봤다면 다음 그림을 통해 Young 영역에 대한 세부적인 과정을 보자

 

● Eden

- new를 통해 새로 생성된 객체가 위치한다.

- 정기적인 쓰레기 수집 후 날아남은 객체들은 Survivor1 또는 Survivor2로 이동한다.

 

● Survivor 0 / Survivor 1

- 최소 1번의 GC 이상 살아남은 객체가 존재하는 영역

- Survivor 영역에는 특별한 규칙이 있는데, Survivor 0 또는 Survivor 1 둘 중에 하나에는 꼭 비어 있어야

  하는 것이다.

 

가비지 컬렉션 알고리즘 종류

여기서 왜 Garbage알고리즘을 배워야 하는지 알 수 있다. 메모리를 개발자가 직접 제어할 수 없다.

하지만 설정을 통해서 Java에 적용할 수 있게 된다. 즉 GC 방식을 알맞게 설정함으로써 메모리 관리를

간접적으로 하기 때문이다.

 

1) Serial GC

- 서버의 CPU 코어가 1개일 때 사용하기 위해 개발된 가장 단순한 GC이다.

- GC를 처리하는 쓰레드가 1개이므로 가장 SWT 시간이 길다.

 

명령어 : java -XX:+UserSerialGC -jar Application.java

2) Parallel GC

- Java 8의 디폴트 GC이다.

- Serial GC와 기본적인 알고리즘은 같지만, Minor GC를 멀티 쓰레드로 수행

 

명령어 : java -XX:+UserParallelGC -jar Application.java

 

3) Parallel Old GC (Parallel Compacting Collector)

- Minor CG + Major CG 멀티 쓰레드 수행

 

명령어 : java -XX:+UserParallelOldGC -jar Application.java

 

4) CMS GC(Concurrent Mark Sweep)

- 어플리케이션의 쓰레드와 GC 쓰레드가 동시에 실행되어 SWT 시간을 최대한 줄이기 위해 고안된 GC 

- GC 대상을 파악하는 과정이 복잡한 여러 단계로 수행되기 때문에 다른 GC 대비 CPU 사용량이 높다.

- 메모리 파편화 문제

- Java9 버전부터는 사용성이 떨어졌고 Java14에서는 아예 사용이 중지

 

명령어 : java -XX:+UserConcMarkSweepGC -jar Application.java

 

5) G1 GC (Garbage First)

- CMS GC를 대체하기 위해 jdk 7 버전에서 최초로  release된 GC

- Java 9+ 버전의 디폴트 GC로 지정

- 4GB 이상의 힙 메모리, STW 시간이 0.5초 정도 필요한 상황에 사용(Heap이 너무 작을 경우 미사용 권장)

- 이전 GC 알고리즘 방식(Major GC, Minor GC 나누는 것)과 다르게 아예 Region이라는 개념을 새로 도입

   Region이라는 영역을 나눠서 기존에 역할을 고정적으로 하는 것이 아닌 동적으로 부여

 

명령어 : java -XX:+useG1GC -jar Application.java

 

6) Shenandoah GC

- Java 12에 release

- 기존 CMS가 가진 단편화, G1이 가진 pause의 이슈를 해결

- 강력한 동시성과 가벼운 GC 로직으로 heap사이즈에 영향을 받지 않고 일정한 pause 시간 소요가 특징

 

명령어 : java -XX:+useShenandoahGC -jar Application.java

 

7) ZGC (Z Garbage Collector)

- Java 15에 release

- 대량의 메모리를 low-latency로 잘 처리하기 위해 디자인 된 GC

- G1의 Region처럼, ZGC는 ZPage라는 영역을 사용하며, G1의 Region은 크기가 고정인데 비해, ZPage는

  2mb 배수로 동적으로 운영됨. (큰 객체가 들어오면 2^로 영역을 구성해서 처리)

- STW의 시간이 절대 10ms를 넘지 않는다.

 

명령어 : java -XX:+UnlockExperimentalVMOptions -XX:+UserZGC -jar Application.java

'Java > 이론' 카테고리의 다른 글

String, StringBuilder, StringBuffer  (0) 2024.06.25
암호화  (0) 2024.06.23
Java Version(8, 11, 17)  (0) 2024.06.22
람다식(Lamda)식  (0) 2024.06.22
TDD(Test Driven Development)  (0) 2024.06.22