새로운 내용을 공부할 때
새로운 내용의 공부를 시작할 때 용어의 정의를 이해하지 못하거나 정확하게 알지 못한다면 그 용어가 포함된 문장을 이해하지 못합니다.
작은 단어 하나가 내용을 이해하지 못하게 하기 때문에 용어를 정확하게 이해하는 것이 중요합니다.
TIL) 불변객체와 GC는 무슨 관계일까
📌 2025-02-26 TIL
1. 오늘의 학습 주제
- stop the world를 알아보니 불변객체가 중요하네
2. 학습 내용
Stop the world를 왜 알아야할까?
자바의 특징은 메모리 관리를 개발자가 하지 않고 GC가 합니다. GC가 메모리를 정리할 때 쓰레드간 참조 일관성을 위해서 잠시 소등하는 것을 우리는 STW라고 합니다.
STW를 알아야하는 이유를 생각해봤습니다.
- 멀티 쓰레드에서 사용하지 않는 메모리를 어떻게 안전하게 정리를 할까
- 우리 서비스가 응답 지연이나 처리량이 낮다는데 원인이 뭘까
JVM 프로세스에서 코드 영역, 데이터 영역, 힙 영역은 공용으로 사용하고 스택은 개별 쓰레드가 사용합니다.
GC는 공용으로 사용하며 동적으로 할당된 메모리를 저장하는 힙 영역의 청소를 맡고 있습니다.
개발자가 직접하지 않고 GC가 메모리를 청소하는 과정에서 발생되기에 어떤 방식으로 처리하는지 알고 있어야 한다고 생각합니다.
그래야 문제가 발생했을 때 원인 후보로 넣을 수도 있으니까요
STW는 왜 길어는 건가
메모리를 정리하려면 사용하지 않는 메모리를 찾아야 합니다.
저는 힙 메모리는 대형 유치원이라고 생각합니다.
아이들(쓰레드)가 장난감(동적 메모리 공간)을 방(힙 메모리)에 뿌리고 갑니다.
유치원 선생님(GC)가 돌아다니며 아이들에게 물어봅니다.
이거 정리해도 되는거지?
장난감 방이 크면 클수록 아이들이 뿌리고 다닌 장난감을 찾아다니는 시간도 길어지는 것처럼 힙 메모리 공간이 크면 클 수록 STW의 시간도 길어집니다.
두 번째는 장난감이 서로 관계가 있다고 생각해봅시다
변신 합체로봇인데 다리 부분, 팔 부분, 머리 부분이 있어야합니다. 이거 하나는 입구에, 다른 하나는 저 끝에 있고 이 변신 합체로봇이 복잡하면 복잡할 수록 유치원 선생님은 하나 하나 아이들이 쓰는지 , 합체에 필요한건지 확인하는 과정이 생깁니다.
세번째는 야외로 유치원 생이 외부로 나간 경우입니다.
유치원 생이 야외에 미끄럼틀을 타기 위해서 외부 놀이기구(JNI)로 갔다면 유치원 선생님은 방 안에서 돌아오기 까지 기다리는 과정이 생깁니다.
네번째는 장난감을 가지고 놀고 있는 아이들을 청소 구역 밖으로 나갈때까지 기다린다.
유치원 선생님(GC)는 아이들(쓰레드)가 가지고 놀다가(동적 메모리) 청소시간이 되면 청소기를 돌려야하니 다치지 않기 위해 아이들을 다른 방으로 보낼때 아이들이 안전한 구역(Safe Point)으로 가기까지 기다려야합니다. 그대로 청소를 하다간 아이들이 다칠 수 있으니까요
실제로는 참조의 무결성으로 참조 정합성을 유지하기 위하여 안전한 지점까지 와야합니다.
안전한 지점이란?
메소드 호출 직후, 루프 종료 등 참조가 변경되지 않은 상태를 말합니다.
그래서 자바 GC는 안전하게 메모리 청소를 합니다.
불변 객체와 STW
대형 유치원에 가면 놀기이구가 있습니다. 항상 상태가 동일하고 위치고 정해져있습니다.
유치원 선생님은 놀이기구를 옴기지 않아도 되고 관리하기도 편합니다. 정리를 하지 않아도 되니까요
불변객체가 그렇습니다. 참조 값이 변경되지 않고, 내부 필드도 값이 변경되지 않는 것을 알고 있기 때문에 제자리로 옴길 필요가 없습니다.
그래서 놀이기구(불변객체)는 빠르게 young 구역에서 old로 옴기려고 합니다.
불변 객체가 몇번동안 gc대상이 아니라면 빠르게 old영역으로 이동시켜서 별도로 관리하는것이 효율적이기 때문입니다.
불변객체가 왜 효율적일까
-
서치할 필요가 없다.
내부 필드(상태)가 처음과 동일하므로 참조가 변경되었는지 확인할 필요가 없습니다.
search 시간 감소
-
압축할 필요가 없다.
gc는 메모리를 정리하고 파편화된 메모리 영역을 효율적으로 저장하기 위해 디스크 정리처럼 메모리를 모아놓습니다. 불변객체는 메모리 영역에서 참조가 변경되지 않으므로 압축 대상에서 제외하면 됩니다.
불변 객체는 참조가 절대 바뀌지 않기 때문에 Young 영역에 오래 두는 것이 비효율적입니다. 몇 번 GC 대상에서 제외되면 바로 Old 영역으로 Promotion하여 메모리 파편화를 방지합니다.
이는 Young 영역에서는 GC가 자주 발생하지만, Old 영역에서는 GC가 덜 발생하기 때문에 STW 시간을 단축하는 효과가 있습니다.
주의사항
불변 객체는 참조 값이 변경되지 않으므로 gc압축 대상에서 제외됩니다. 그러다보니 스펀지 마냥 군데 군데 비어있게 되는 상태가 됩니다.
그걸 방지하고자 가변 객체와 다르게 old영역에 빠르게 promotion합니다.
이유는 메모리 압축 대상도 아니고 몇번동안 살아남으면 메모리 파편화가 많아지기 전에 빠르게 gc old 영역으로 이동시킵니다.
만약 불변 객체가 이동하지 않는다면 듬성 듬성 정리되지 않은 메모리가 생기기 때문입니다.
댓글남기기