본문으로 바로가기

Garbage Collection Part1

category Java 개발 이야기 2020. 12. 6. 23:39
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

최근 메모리 관련 문제라고 생각되는 이슈가 있어서, GC 로그를 보게 되었고, 로그 분석을 하다가 GC에 관해서 다시 공부하고 재정립하는 시간을 갖게 되었다. 이 내용을 공유하고자 오랫만에 블로그에 글을 올린다.\


GC종류에 대해서 설명하기 전에 알아야 할 개념 몇 가지가 있다.


1. Stop-the-world

GC를 실행하기 위해 어플리케이션 실행을 멈춘다. 효율적인 GC 알고리즘을 작성하는 것은 Stop-the-world의 시간을 줄이는 것이다.


2. Reachable와 Unreachable

GC에 의해 사용하지 않는 객체는 삭제되는데, 어떤 방식으로 유효한건지 판별하는걸까 ?

아래에서 그림에서 GC Roots를 참조할 수 있는 모든 객체를 Reachable, GC Roots 참조할 수 없는 객체를 Unreachable이라고 한다. 참조 트리에서 유효한 객체인지 확인하기 위해서 항상 유효한 최초의 객체가 존재해야 하는데 이를 GC Root라고 한다.




자세한 설명은 우하한 테크톡 "엘리의 GC"편을 보면 좋을 것 같다.


3. Mark, Sweap, Compact

http://www.cs.columbia.edu/~aho/cs6998/Lectures/14-10-27_Li_GarbageCollection.pdf



GC의 기본 프로세스는 Mark and Sweap 이라고 할 수 있다.


참조되지 않는 객체를 실벽하는 Mark, Marking된 객체를 삭제하는 Sweap, Sweap 후 발생한 메모리 단편화 문제를 해결하기 위한 Compact


4. JVM 메모리 구조에 대해

JVM 메모리 구조에 대해서는 "JVM 메모리 구조 이해하기" 편에 정리를 해 놓았다. 


여기 까지 내가 아는 기본적인 용어와 배경 지식에 대해서 정리를 해놓았다.

이제 GC종류에 대해서 알아보자.


5. 왜 Young Generation, Old Generation, Minor GC, Major GC가 나왔을까, 그냥 한번에 모든 메모리를 통합하는 GC를 사용하는게 좋지 않을까 ?


https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html


위의 질문은 누구나 생각하고 의문을 표할 수 있다고 생각되고, 왜 이렇게 나눠놨는지 오라클 GC 튜토리얼에 씌여있다.


As stated earlier, having to mark and compact all the objects in a JVM is inefficient. As more and more objects are allocated, the list of objects grows and grows leading to longer and longer garbage collection time. However, empirical analysis of applications has shown that most objects are short lived. 

JVM에 있는 모든 Object를 GC하는 것은 비효율 적이다, 더 많은 객체들이 메모리에 할당 됨으로써 GC의 시간이 길어지게 될 뿐이다. Application의 분석에 따르면 대부분의 객체의 생명주기는 매우 짧다.


As you can see, fewer and fewer objects remain allocated over time. In fact most objects have a very short life as shown by the higher values on the left side of the graph.

위의 표를 보면 알 수 있다. 시간이 지날 수록 객체들은 할당되고, 실질적으로, 대부분의 객체는 매우 짧은 수명을 갖고 있고 그래프의 왼쪽 부분을 보면 알 수 있다.


"weak generational hypothesis"라는 가설이 있다.


1. 대부분의 객체는 금방 접근 불가능한 상태가 된다. 

대부분의 객체는 중괄호 안에서 생성된다. 이 객체들은 괄호가 끝나면 사용되지 않습니다. 


2. 오래된 객체에서 젊은 객체로의 참조는 적다

일반적으로 대부분의 비지니스 로직은 순차적으로 객체가 생성되고 사용됩니다.

앞에서 생성된 객체는 다음 로직에서 사용된 이후 대부분 사용되지 않습니다.



GC Process 

GC가 일어나는 과정에 대해서 살펴본다. 모든 이미지와 설명은 Oracle 사이트를 참조하였다.


1. 

First, any new objects are allocated to the eden space. Both survivor spaces start out empty. 

새로 생긴 객체는 eden 영역에 생성되고, 두개의 survior space는 비어있는 상태로 시작된다.


s0에 있는 3,1은 s0에서 s1로 옮겨진다라는 걸 보여주기 위해 표현된 것 같다.

2.

When the eden space fills up, a minor garbage collection is triggered.

Eden 영역이 꽉 찼을 때 minow GC가 시작된다. 


3. 

Referenced objects are moved to the first survivor space. Unreferenced objects are deleted when the eden space is cleared.

참조된 객체 (여기서는 Reachable 가능한 객체를 의미하는 것 같다.) 는 survivor space 영역으로 옮겨지고 참조불가능한 객체들은 eden 영역에서 삭제된다


4.

At the next minor GC, the same thing happens for the eden space. Unreferenced objects are deleted and referenced objects are moved to a survivor space. However, in this case, they are moved to the second survivor space (S1). In addition, objects from the last minor GC on the first survivor space (S0) have their age incremented and get moved to S1. Once all surviving objects have been moved to S1, both S0 and eden are cleared. Notice we now have differently aged object in the survivor space.


첫 번째 GC가 일어난 다음에 Eden영역에 객체가 생성되고 꽉차게 되면 minor GC가 일어난다. 똑같이 참조불가능한 객체는 삭제되고, 참조가능한 객체는 survivor영역으로 옮겨지는데 s0이 아닌 s1영역으로 옮겨진다. 그리고 s0에서 s1로 옮겨진 객체들의 age는 1씩증가된다.


여기서 주의할 점은 s0 그리고 s1 둘중에 하나는 무조건 비어져 있어야 한다.

5.

At the next minor GC, the same process repeats. However this time the survivor spaces switch. Referenced objects are moved to S0. Surviving objects are aged. Eden and S1 are cleared.


다시 Minor GC가 발생했을 때 똑같이 반복한다. 아래 사진을 보면 s1-> s0영역으로 다시 옮겨지고 age가 1씩증가하며 Eden과 S1영역이 비어진다. 


6. 

This slide demonstrates promotion. After a minor GC, when aged objects reach a certain age threshold (8 in this example) they are promoted from young generation to old generation.


위의 과정을 끊임없이 반복하면서 특정 객체의 age는 한계점에 도달한다 (아래 이미지에서는 한계점이 8로 설정) age가 8이 넘어가면 Old Generation으로 옮겨진다. Young Generation -> Old Generation으로 넘어가는 넘어가는 것을 Promotion이라 한다.

 


7.

As minor GCs continue to occure objects will continue to be promoted to the old generation space.

Minor GC가 계속해서 발생함으로써, Old Generation 으로 계속해서 promoted 하게 된다.

위에서 설명한 promotion이 계속해서 발생한다는 뜻이다.


8.

So that pretty much covers the entire process with the young generation. Eventually, a major GC will be performed on the old generation which cleans up and compacts that space.

Young Generation에 대한 전반적인 프로세스 절차에 대해서 다루었다. 마지막으로 Major GC는 Old Beneration영역에서 수행되고 사용하지 않은 객체는 사라지고 Compacts 과정이 일어난다.



전반적인 GC 절차에 대해서 살펴보았다.

다음편에는 GC종류 그리고 Java 8로 인해 바뀐 JVM 구조에 대해서 설명한다.