자바의 메모리구조를 이야기하기전에 JVM에대해서 설명해보자
JVM은 Java Virtual Machine의 약자로써
일반적인 프로그램이 OS위에서 동작하는데 반해
자바 프로그램은 OS위의 JVM에서 동작한다.
이것은 플랫폼에 독립적인 자바의 특징을 보여주며,
자바로 작성된 프로그램이 플랫폼에 무관하게 동작하고,
이러한 프로그램이 최적의 성능으로 돌아가기 위해서는
JVM의 동작을 잘 이해하는 것이 필요하다.
JVM의 영역은 크게 아래와 같이 나뉜다.
1. Class Loader
> JVM에서 Runtime Data영역으로 클래스를 로드하고 Linking한다.
> Runtime시 동적으로 로드가 가능하다.
2. Execution Engine
> Class Loader에서 Runtime Data영역으로 로드된 클래스의 바이트 코드를 실행
> 실행 엔진은 자바의 바이트코드를 명령어 단위로 읽어서 실행
3. Garbage Collector
> Garbage Collection을 수행하는 모듈 쓰레드를 지칭한다.
> 사용되지 않는 메모리를 확보하는등의 메모리 관리를 수행한다.
4. Runtime Data Area
> JVM이 OS로부터 할당받는 메모리 영역으로 6가지로 나뉜다.
JVM의 기본적인 수행 절차는 다음과 같다.
1. 자바로 프로그램 코드를 작성(.java)
2. 컴파일 과정을 통해 바이트코드 생성(.class)
3. 클래스 로더에서 런타임 데이터 영역으로 적재한다.
4. 적제된 코드에 대한 정보를 런타임 영역이 가지고 있고
5. Execution Engine을 통해 실행된다.
JVM의 런타임 영역은 다음과 같이 나뉜다.
1. 클래스 영역
2. 스태틱 영역
3. 상수 영역
4. 힙 영역
5. native 메소드 영역
6. PC 레지스터
힙 영역에서 GC가 일어나는데
힙은 기본적으로 Young영역과 Old 영역으로 나뉜다.
이렇게 두가지로 나뉜 배경에는
첫째로 대부분의 객체는 금방 접근 불가능한 상태가 되며,
두번째는 오래된 객체에서 신규 객체로의 참조는 거의 없다는 것을 전재로 한다.
객체가 Young영역에서 Old영역으로 이동하는것을 Minor GC라고 하고
Old영역이 가득차 객체가 삭제되는 것을 Major GC라고 한다.
Young영역은 또 크게 3가지 영역으로 나뉘는데,
객체가 가장 먼저 등록되는 Eden영역,
그리고 이 객체들이 이동하는 두개의 Survivor영역이다.
하나의 Survivor영역이 가득차면 살아남은 객체를 두번째 Survivor영역으로 이동하고
가득찬 Survivor영역에서 GC가 일어난다.
그렇기때문에 두개의 Survivor영역중 하나는 무조건 비어있어야한다.
Major GC가 일어나면 STW(Stop the world)라는 현상이 발생하는데
JVM내에서 GC를 제외한 어플리케이션이 멈추는 현상으로
이는 서비스에 치명적이기 때문에 Major GC를 최소화하는 전략이 중요하다.
GC의 알고리즘은 몇가지로 나뉘는데
1. 시리얼 알고리즘
- 적은 메모리와 적은 코어에 적합 (정렬방식)
2. 병렬 알고리즘
- GC를 처리할때 멀티 쓰레드를 지원
3. CMS 알고리즘
- STW 시간이 짧지만 메모리와 CPU의 사용이 많음 (바둑판방식)
4. G1(Garbage First)알고리즘
- 최신 알고리즘. 성능이 가장 좋다. 대규모에 적합
- Young영역을 나눠서 GC. STW 발생
- Old 영역을 나눠서 STW없이 GC.
등이 있다.