런타임 데이터 영역
이전 글에서 클래스 로더와 실행 엔진에 대해 살펴보았다. 이제 남은 것은 JVM 실행시에 데이터를 저장하는 런타임 데이터 영역이 남았다. 사실 Native Method Interface와 Native Method Library가 있긴 하지만, 이름에서 알 수 있는 내용이 전부다. Java에서 C/C++같은 다른 언어들을 사용할 수 있도록 해주는 역할이다.
[이미지 출처] https://www.baeldung.com/java-compiled-interpreted
다시 런타임 데이터 영역으로 돌아오면, 위의 그림에서 볼 수 있듯이 5가지 영역으로 구성된다. 하나씩 살펴보도록 하자.
메소드 영역
메소드 영역은 이미 본 적이 있다. 클래스 로더에서 바이트코드를 로딩하면 바로 이 메소드 영역에 올라오게 된다. 따라서 바이트코드에 있는 클래스와 메소드에 대한 정보, static 변수, constant pool 등의 모든 정보가 메소드 영역에 저장된다. Java 7까지는 PermGen이라는 이름으로, JVM 시작시에 고정된 크기를 가졌다. 그러나 Java 8부터는 Metaspace라는 이름으로 바뀌면서 가비지 컬렉션의 대상이 되었으며, 로딩된 클래스에 따라 크기가 동적으로 변하도록 바뀌었다. 메소드 영역은 모든 스레드가 공유한다.
힙 메모리
힙은 동적으로 메모리를 할당받을 수 있는 공간이다. 배열을 선언하거나, 클래스의 인스턴스를 생성하면 바로 힙 메모리가 할당된다. 가비지 컬렉터에 의해 메모리가 관리되며, 크게 young 영역과 old 영역으로 구분할 수 있다. Young 영역은 새롭게 할당된 메모리가 위치하는 곳이며, 이곳에서 일어나는 GC를 minor GC라고 한다. Old 영역은 minor GC에서 오랫동안 살아남은 객체들이 이동하는 곳으로, 이곳에서 일어나는 GC는 major GC라고 한다. 힙 메모리도 모든 스레드가 공유하여 사용한다.
스택 메모리
스택 메모리는 메소드 호출에 의해 할당되는 공간이다. 메소드 호출이 될 때 할당되는 메모리를 스택 프레임이라고 하며, 각 스택 프레임은 로컬 변수와 중간 결과, 결과를 리턴할 주소 등을 포함하고 있다. 스택의 가장 큰 특징은 스레드마다 스택 메모리를 하나씩 가진다는 것이다. 각 스레드는 다른 메소드를 실행할 수 있다는 것을 생각해보면 당연한 것이다.
PC 레지스터
PC 레지스터는 다음에 실행할 명령어(Program Counter)를 저장하는 곳이다. 스택과 마찬가지로 스레드마다 다른 메소드를 실행할 수 있기 때문에 공유되지 않는다. 만약 네이티브 메소드를 실행하는 경우, PC 레지스터의 값은 정의되지 않는다.
네이티브 메소드 스택
네이티브 메소드 스택은 이름 그대로 네이티브 메소드가 사용하는 스택 메모리다. 네이티브 메소드는 Java가 아닌 다른 언어로 정의된 메소드를 말하며, JNI(Java Native Interface)로 네이티브 메소드를 실행할 수 있고, 실행중인 메소드의 상태를 네이티브 메소드 스택에 저장한다. 스택 메모리와 마찬가지로 스레드별로 다른 공간을 가진다.
3줄 요약
- JVM은 클래스 로더, 실행 엔진, 런타임 데이터 영역으로 구성된다
- 런타임 데이터 영역은 또 5가지 영역으로 구분된다
- 힙과 메소드 영역은 여러 스레드가 공유하므로 주의해서 사용하자
'Java > 자바 최적화' 카테고리의 다른 글
[Java] 자바 최적화(6) - 가비지 컬렉션 기초 (0) | 2023.03.26 |
---|---|
[Java] 자바 최적화(5) - 마이크로 벤치마킹 (0) | 2023.03.23 |
[Java] 자바 최적화(3) - 실행 엔진 (0) | 2023.03.17 |
[Java] 자바 최적화(2) - 클래스 로더 (0) | 2023.03.16 |
[Java] 자바 최적화(1) - 성능 지표 (0) | 2023.03.15 |