백엔드 개발자라면 면접에서 99% 물어보는 Garbage Collection(GC)에 대해 확실하게 정리하고 넘어가보자.
* 아래 링크를 참고하여 번역 및 정리하였습니다.
https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
https://www.geeksforgeeks.org/garbage-collection-java/?ref=gcse
1. Garbage Collection이란?
1) Garbage Collection의 정의
가비지 컬렉션이란, Heap 메모리에서 사용되지 않거나 더 이상 참조되지 않는 객체(가비지)를 찾아서 메모리에서 수집하여 제거하는 것을 말한다.
C/C++에서는 프로그래머가 직접 메모리를 할당하고 free()를 이용하여 해제해 주어야 하지만 자바는 JVM에서 Garbage Collector를 호출하여 자동으로 메모리를 해제해준다.
2) JVM에게 가비지 컬렉터를 호출하는 방법(사실 상 동일)
System.gc()
메소드 호출Runtime.getRuntime().gc()
메소드 호출
3) Finalization
객체를 제거하기 직전에 GC는 객체에 대한 finalize()
메서드를 호출하여 정리작업을 수행한다. finalize()
메서드가 종료되면 GC는 객체를 제거한다.
// Object class에 존재한다.
protected void finalize() throws Throwable
필요에 따라 finalize()
메서드를 오버라이딩하여 DB 커넥션 해제와 같은 정리 작업을 직접 정의할 수 있다.
- finalize()
는 JVM이 아닌 GC에 의해 호출된다.(GC는 JVM의 모듈 중 하나임)
- finalize()
는 아무것도 정의되어 있지 않기 때문에 시스템 리소스를 삭제하거나 다른 정리를 수행하도록 재정의하는 것이 좋다.
- finalize()
는 객체를 위해 한 번 이상 호출되지 않는다.
- finalize()
에 의해 잡지 못하는 예외처리가 발생할 경우 예외는 무시되며 객체 삭제가 종료된다.
4) Java에서 가비지 컬렉션의 장점
GC가 참조되지 않는 객체들을 힙에서 제거해주기 때문에 자바 메모리를 효과적으로 사용할 수 있다.
GC에 의해 자동으로 수행되기 때문에 직접 메로리를 해제하는 등 프로그래머의 별도의 노력이 필요하지 않다.
2. Garbage Collection의 핵심
Garbage Collection의 대상
1) Unreachable Objects
더 이상 어떠한 참조도 일어나지 않는 객체
String name = new String("old Name");
name = new String("new Name"); // old Name은 unreachable됨
* reachable
힙 객체들에 대한 참조는 4가지 중 하나이다.
1) Heap 내의 다른 객체에 의한 참조
2) Java Stack, 즉 Java 메서드 실행 시 사용하는 지역 변수와 파라미터들에 의한 참조
3) Native Stack, 즉 JNI(Java Native Interface)에 의해 생성된 객체에 의한 참조
4) Method Area의 정적 변수에 의한 참조
이 중 힙 내의 다른 객체에 의한 참조를 제외한 나머지 3개에서 참조될 경우 reachable로 판단되며, reachable한 객체가 참조되고 있는 객체 또한 reachable이 된다.
2) GC의 대상이 되는 객체(Eligibility for Garbage Collection)
- Nullifying the reference variable(null로 할당된 참조변수)
- Re-assigning the reference variable(재할당된 참조변수)
- An object created inside the method(메소드 내부에서 생성된 지역변수/객체)
- Island of Isolation*
Java에서 객체들의 제거는 Garbage Collector(GC)에 의해 처리된다. GC는 어디에도 참조되지 않는 unreachable한 객체들을 찾아서 메모리를 회수한다. 여기서 앞선 Garbage Collection에 관한 포스팅에 잠깐 등장했던 Island of Isolation(고립된 섬)이라는 개념이 등장하는데 정확히 어떤 의미인지 알아보려고 한다.
객체A와 객체B가 서로 참조하며 다른 객체들은 객체A과 객체B를 모두 참조하지 않을 때 이 둘을 Island of Isolation이라고 한다. 엄밀히 말하면 서로 참조하는 객체 A, B뿐만 아니라 아무도 참조하지 않는 하나의 객체C와 객체D 또한 Island of Isolation으로 볼 수 있다.
Stop The World(STW)
GC가 일어날 때 GC를 담당하는 쓰레드를 제외한 모든 쓰레드들이 일시적으로 정지되는 현상을 STW라고 한다.
모든 쓰레드가 정지되기 때문에 어떠한 작업도 실행되지 않기 때문에 잦은 GC는 여유 메모리를 확보해주는 장점이 있지만 성능이 저하되는 문제가 발생한다.
GC의 핵심은 적절한 빈도의 GC가 실행되도록 하여 STW가 자주 발생하지 않는 것과, GC의 시간을 단축하여 STW 시간을 줄이는 것이다.
Card Table
드물지만 Old Generation의 객체가 Young Generation의 객체를 참조하는 경우가 존재한다. 이를 위해서 Minor GC가 일어날 때마다 Old Generation의 객체까지 모두 조회하는 것은 비효율적이기 때문에 이를 대비하여 Old Generation에는 512 byte의 Chunk로 되어 있는 카드 테이블(Card Table)이 존재한다.
카드 테이블에는 Old Generation의 객체가 Young Generation의 객체를 참조할 때마다 Card Table에 정보가 표시되며 Minor GC가 일어날 때마다 카드테이블을 조회하여 GC대상인지 식별한다.
'백엔드' 카테고리의 다른 글
[Java] Collection.stream().forEach() 와 Collection.forEach() 의 차이 (0) | 2022.06.27 |
---|---|
[Java] 2. Garbage Collection - GC의 과정 및 종류 (0) | 2022.06.24 |
[Java/Postgresql] 랜덤 문자열 생성 - get_random_string() (0) | 2022.03.21 |
[Spring] Spring MVC 구조 - Dispatcher Servlet 이란? (0) | 2022.02.04 |
[Java] equals()와 ==의 차이점(feat: String str=""와 new String("")의 차이점) (0) | 2022.02.03 |
댓글