Java GC

이불빨래장인·2022년 7월 21일
0

CS

목록 보기
2/2
post-thumbnail

JAVA Garbage Collector

누구나 들어봤을 GC. c 혹은 c++과 java가 가장 다른 부분임과 동시에 java가 느린 원인으로도 손꼽힌다. 이에 대해 공부하고 GC가 일어나지 않게끔 코딩하는 습관을 들여야 할 것 같다.


GC 종류


  • reference counting 방식
  • Mark & Sweep 방식
  • Mark & Compact 방식 (현재 java에서 쓰이는 방식)

기본 개념


  1. java는 c++, c와 다르게 포인터가 없다. (정확히는 개발자에게 제공하지 않는다.)
  2. java는 c++, c와 다르게 모든 객체 (primitive type 제외) 를 heap 영역에 저장한다.

위 개념과 함께 GC의 종류와 작동원리를 배워보자


1. Reference Counting 방식.


각 객체마다 reference count 값을 가지고 아무도 참조하고 있지 않다면 (reference count 값이 0 이라면) GC의 대상이 된다.

이는 각 객체마다 값이 관리되기 때문에 GC의 타이밍이 분산되고 이해하기 쉽다는 특성이 있지만 순환 참조가 되고 있다면 GC의 대상이 아니게 된다는 점, 참조수가 많은 객체의 경우 reference count가 0 이 된다면 연쇄적인 GC가 일어날 수 있기 때문에 효율이 좋지 못하다.
또한 객체별로 reference count 값들을 관리해줘야 하기 때문에 비용이 많이 든다.

ex) 정상적인 reference count를 통한 GC

이때 Integer(value 100)의 객체는 GC의 대상이 된다.

ex) 순환참조로 인해 GC가 발생하지 않는 경우

밑의 빨간색 부분은 서로 참조하고 있으므로 reference count 가 1이고 GC의 대상이 아니게 된다.


2. Mark & sweep / Mark & Compact 방식.


이 두 가지 방식은 메모리 공간 관리의 차이가 있을 뿐 GC의 원리는 같으므로 같이 설명한다.

전제: 자바는 새로 생성된 객체는 금방 사라질 것이라는 가정, 오래된 객체로부터 새로 만들어진 객체로의 참조는 적을 것이라는 가정, 이 두가지 가정을 전제로 heap 영역을 관리한다.
기초: Major GC / Minor GC 모두 stop-the-world가 일어나게 되며 모든 thread가 멈춘다 (GC thread 제외)


2.1 JVM 메모리 관리

위 전제에 따라 jvm은 이런식의 메모리 구조를 가지고 있다.

순서)
1. 새로 만들어진 객체는 Eden에 생성된다. 이 객체들은 age-bit을 가지게 되며, eden 영역이 다 차게 되면 살아남은 객체들은 survival 로 이동한다.(Minor GC 발생)
2. survival 영역에 있는 객체들은 Minor GC가 일어날 때 마다 age-bit이 1씩 증가하며 (이 때도 eden에는 새로운 객체들이 계속 생성된다.) age-bit의 수가 일정 부분 넘어선다면 Old Generation 영역으로 이동하게 된다. (promotion 발생)
3. Old Generation의 영역이 다 차게 된다면 이 때 Major GC가 일어난다!


2.2 GC 작동 방식

순서)
1. Root Set에서 참조하는 객체들의 mark-bit을 true로 만든다.
2. mark bit이 false인 객체들을 없앤다. (위 그림과 같이 순환참조되는 객체도 삭제가능) (이 처럼 mark-bit이 true 인 것을 reachable object, false를 unreachable object 라 한다.)



위 과정이 GC의 대략적인 과정이다. 그럼 여기서 mark & sweep 과 mark & compact 방식의 차이, Root Set의 정체에 대해 알아보자.


Mark & Compact


위 그림은 mark & sweep의 예시였다. heap 영역의 데이터들을 따로 삭제하면 fragmentation 문제가 발생하기 때문에 mark & sweep 방식에 compact 과정을 추가한게 mark & compact 방식이다.

이 처럼 파편화된 데이터를 모아주는 것. (디스크 조각모음 같음)


Root Set


  1. JVM Stack 내의 Local Variable Section과 Operand Stack에서의 참조 (Java 메서드 내에서 실행하는 지역 변수 또는 파라미터에 의한 참조)

  2. JVM Method Area의 Constant Pool에서 참조 (정적 변수에 의한 참조)

  3. 아직 메모리에 남아 있는 Native Method로 넘겨진 Object에서 참조 (JNI에 의해 생성된 객체에 대한 참조)

위 세 가지 형태의 root에서 출발하여 객체들의 reachablility를 판단한다.


Reference

https://coding-factory.tistory.com/829

https://medium.com/@joongwon/jvm-garbage-collection-algorithms-3869b7b0aa6f

https://www.baeldung.com/java-gc-roots

profile
잡다한 것에 관심이 많은 사람

0개의 댓글