Garbage Collection
stop-the-world!
GC 실행 중에는 애플리케이션이 멈춘다. GC를 실행하는 쓰레드를 제외한 나머지 모든 쓰레드가 작업을 멈춘다.
어떤 GC 알고리즘이라도 stop-the-world는 발생한다. GC 튜닝은 대개 이 stop-the-world 시간을 줄이는 것이다.
메모리를 명시적으로 해제할 때?
해당 객체를 null로 지정하기
System.gc() 호출하기 -> 절대 하지 말 것. 성능저하!
가비지 컬렉터의 두 가지 가설 - Weak Generational Hypothesis
1. 대부분의 객체는 금방 접근 불가능 상태(unreachable)가 된다.
2. 오래된 객체에서 젊은 객체로의 참조는 아주 드물게 존재한다.
Young Generation / Old Generation
HotSpot VM에서는 위 가설에 따라 젊은 객체와 오래된 객체의 물리적 공간을 나누었다.
Young Generation
새롭게 생성된 객체의 대부분이 위치한다.
여기서 일어나는 GC는 Minor GC.
Young 영역은 다시 Eden 영역과 두 개의 Survivor 영역으로 나뉘어진다.
새로 생성한 객체는 Eden 영역에 먼저 저장되고, Eden 영역의 GC에서 살아남은 객체만 둘 중 사용 중인 Survivor 영역으로 이동된다.
Survivor 영역이 가득 차면, GC가 일어나면서 살아남은 객체들만 비어있던 다른 Survivor 영역으로 옮겨진다.
이 과정을 반복한 뒤에도 살아남는 객체만 Old 영역으로 옮겨간다.
HotSpot VM에서는 최적화를 위해 아래 두 가지 기술을 사용한다.
bump-the-pointer
빠르게 메모리 할당을 하기 위해 적용된 기술이다.
새로 생성하려는 객체가 Eden 영역에 저장할 수 있는 크기인지 판단할 때, Eden 영역에 저장된 마지막 객체의 위치만 확인한다.
TLABs(Thread-Local Allocation Buffers)
Lock 없이 Thread-safe하게 만들기 위해 적용된 기술이다.
Eden 영역을 쪼개서 각 스레드에 나누어준다. 각자의 TLAB 안에서만 메모리 할당이 이루어지기 때문에 락이 필요없다.
Old Generation
Young 영역에서 살아남은 객체가 여기로 복사된다.
대부분 Young 영역보다 크게 할당하기 때문에 GC는 적게 발생한다.
여기서 일어나는 GC는 Major GC(혹은 Full GC).
Permanent Generation (Method Area)
클래스 정보나 intern된 문자열 정보 등을 저장하는 곳.
여기서 일어나는 GC도 Major GC에 해당된다.
=> Java 8부터 Permgen을 Metaspace가 대신하게 되었다. (Metaspace는 메모리 할당량을 유동적으로 조절한다.)
Old 영역에 있는 객체가 Young 영역의 객체를 참조할 때?
Old 영역에는 512바이트 짜리 Card Table이 존재한다.
Old 영역의 객체가 Young 영역의 객체를 참조할 때마다 여기에 표시하고, Minor GC가 일어날 때 표시된 영역만 검사한다.
Card Table은 Minor GC가 일어날 때 어디에서 Young 영역의 객체가 참조되고 있는지 확인하는 용도로 사용된다.
Old 영역을 일정하게 쪼개어 각 조각들과 대응되도록 축소판을 만들어 놓았다고 보면 된다.
Young 영역을 참조하려할 때, 그 객체가 속해있는 메모리 영역의 카드를 Dirty 상태로 표시한다.
덕분에 Minor GC를 실행할 때는 이 Dirty 영역에 들어있는 Old 객체들의 참조만 확인하면 된다.
카드 마킹 시 Write Barrier를 사용하기 때문에 오버헤드가 발생하지만, GC 시간을 줄이기 위한 기회비용이라고 본다.
Write Barrier : 객체를 생성하거나 재할당할 때마다 확인해서 카드마킹 하는 방식.
https://en.wikipedia.org/wiki/Write_barrier
Write barrier - Wikipedia
en.wikipedia.org
http://psy-lob-saw.blogspot.com/2014/10/the-jvm-write-barrier-card-marking.html
The JVM Write Barrier - Card Marking
Blog on Java, Performance, Concurrency, NIO, Unsafe, Low latency, Programming, Software, Philosophy
psy-lob-saw.blogspot.com
https://blogs.msdn.microsoft.com/abhinaba/2009/03/02/back-to-basics-generational-garbage-collection/
Back To Basics: Generational Garbage Collection
This post is Part 8 in the series of posts on Garbage Collection (GC). Please see the index here. One of the primary disadvantage discussed in the post on mark-sweep garbage collection is that it introduces very large system pauses when the entire heap is
blogs.msdn.microsoft.com
Full GC 알고리즘
mark-sweep-compact 알고리즘
살아있는 객체를 식별(mark)한 후, 힙의 앞부분부터 살아있는 객체만 남긴 다음(sweep), 빈 부분을 채워서 메모리를 정리한다(compact).
Serial GC와 Parallel GC가 사용하는 방식이다. Parallel Old GC는 조금 더 복잡한 Mark-Summary-Compaction 알고리즘을 사용한다.
Concurrent-mark-sweep GC (CMS GC)
Initial Mark -> Concurrent Mark -> Remark -> Concurrent Sweep 로 단계를 나누어 stop-the-world 시간이 매우 짧다.
대신에 메모리와 CPU를 많이 사용하고, Compaction 단계를 기본적으로 거치지 않기 때문에 주의해야 한다.
애플리케이션의 응답속도가 매우 중요할 때 사용하며, Low-Latency GC라고도 부른다.
Garbage First GC (G1 GC)
CMS GC를 대체하기 위해 만들어진 방식으로 기존의 Young/Old 방식을 사용하지 않는다. JDK 7부터 정식으로 제공되었다.
'software engineering > web' 카테고리의 다른 글
Java의 File Path 상대경로 (0) | 2020.04.06 |
---|---|
Spring 5.2, SpringBoot 2.2 Http Codec이 변경되었다. (0) | 2019.10.25 |
JPA EntityListener가 Bean을 주입 받지 못하는 이유 (0) | 2019.10.15 |
해싱 Hashing (0) | 2019.10.03 |
토비의 봄 TV - 스프링 리액티브 프로그래밍(1) (0) | 2019.09.25 |