자바 애플리케이션을 실행하면 JVM이 OS로부터 메모리 공간을 할당받고 JVM은 할당받은 메모리를 용도에 따라 여러 영역으로 나누어 관리하게 되는데, 이렇게 관리하는 전체 영역을 Runtime Data Area라고 부릅니다.
메모리 영역은 Method Area, Heap Area, Stack Area, PC register, Native Method Stack으로 나뉩니다.
위 사진에서 보이듯이 Method Area, Heap Area 영역은 모든 Thread가 공유하고 Stack Area, PC register, Native Method Stack 영역은 Thread 별로 생성됩니다.
쓰레드(Thread)와 프로세스 - 작성 예정
모든 Thread가 공유하는 Method Area, Heap Area는 JVM 시작 시 생성되고 JVM이 종료 시 소멸합니다.
그리고 나머지 영역은 쓰레드가 생성될 때 생성되고, 쓰레드 종료될 때 소멸합니다.
Thread별로 생성되는 영역
Native Method Stack
Java로 작성된 프로그램을 실행하면서, 순수하게 Java로 구성된 코드만을 사용할 수 없는 시스템의 자원이나 API가 존재하는데, 이렇게 다른 프로그래밍 언어로 작성된 메서드들을 Native Method라고 합니다. Native Method Stacks는 이런 Native Method를 다루는 영역을 말하며, ‘C Stacks’라고도 불립니다.
PC(Program Counter) Register
JVM은 한 번에 많은 Thread를 실행할 수 있고, 각 Thread는 각자의 메서드를 실행합니다. 이때 Thread별로 동시에 실행하는 환경이 보장되어야 하므로 PC Register는 Thread에서 실행할 다음 명령어의 주소를 저장합니다.
다음 명령어의 주소를 저장하는 이유 CPU는 스레드 사이를 전환하며 명령을 수행하기 때문에 Context Switching이 일어나는 순간에 실행할 위치를 알아야 하기 때문입니다. 이것을 이용해 다수의 쓰레드들이 명령의 흐름을 잃지 않고 실행될 수 있습니다.
Stack Area
JVM Stack은 Thread에서 로컬 변수, 부분 결과, 메서드 호출 및 반환에 대한 데이터를 저장하는데 사용됩니다.
각 Thread는 메서드를 호출할 때마다 Frame이라는 단위로 Stack Area에 추가합니다.
메서드가 실행되어 결과를 반환하면 해당 Frame은 Stack Area에서 제거가 됩니다.
Frame 프레임은 데이터 및 부분 결과를 저장, 동적 연결, 메서드 결과값 반환, 예외 전달을 수행합니다. 프레임은 메서드 호출이 완료되면 결과가 정상이든 갑작스러운 종료(예외 발생)이든 상관없이 없어집니다.
Frame은 Local variable array, Oerand stack, Constant Pool reference 이렇게 세부분으로 나뉩니다.
Local Variable : 메서드 안의 지역 변수들이 있는 공간 Operand Stack : 메서드 내 연산을 위해서, 바이트 코드 명령문들이 들어있는 공간 Constant Pool Reference : Constant Pool 참조를 위한 공간
모든 Thread가 공유하는 영역
Method Area
Class/Interface에 대한 Metadata를 저장합니다.
클래스 로더에 의해서 로드된 Class의 정보(Class의 Method, Field이름, Field타입, Class이름 등)가 여기에 저장됩니다. 또한, Runtime Constant Pool과 static 변수와 같은 것들도 저장이 됩니다. Method Area는 Heap Area의 일부일 수도 있고 아닐 수도 있으며, 이를 저장할 위치를 결정하는 것은 전적으로 JVM 구현에 달려 있습니다.
PermGen, MetaSpace
Java8 버전 이전에서는 Method Area는 PermGen(Permanent Generation Space)에 할당되었습니다.
PermGen은 OS, JVM 버전마다 각기 다른 default 값을 가지고 있었고, 대부분 작게 할당되어 있었습니다. 그래서 클래스 로딩을 많이 하게 되면 PermGen이 부족해 에러가 발생했는데,
Java8 버전 이후에는 PermGen이 완전히 제거되고 Method Area는 MetaSpace에 할당됩니다. MetaSpace는 Class의 Metadata를 Native 메모리에 저장하고 부족할 경우 자동으로 늘려줍니다.
Heap Area
Heap Area은 메서드 안에서 사용되는 객체들을 위한 영역으로 new를 통해 생성된 객체, 배열, immutal 객체 등의 값이 저장됩니다. 해당 영역에서 생성된 객체들은 JVM Stack Area의 변수나 다른 객체의 필드에서 참조가 가능합니다.
따라서, Heap 에서는 참조되지 않는 인스턴스와 배열에 대한 정보 또한 있을 수 있기 때문에 GC의 주 대상이 됩니다.