JVM
- JVM은 Java Virtual Machine의 약자로, 자바 가상 머신이라고 부릅니다. 그리고 자바와 운영체제 사이에서 중개자 역할을 수행
- 자바가 운영체제에 구애 받지 않고 프로그램을 실행할 수 있도록 지원
- 가비지 컬렉터를 사용한 메모리 관리도 자동으로 수행
- 레지스터 기반이 아닌 스택 기반으로 동작
- 자바 컴파일러에 의해 자바 소스 파일은 바이트 코드로 변환
- 바이트 코드를 JVM에서 로딩
- 운영체제에서 프로그램을 실행
Java Stack / Heap
Stack
- Heap 영역에 생성된 Object 타입의 데이터의 참조 값이 할당
- 원시타입의 데이터가 값과 함께 할당
- 원시타입의 데이터들에 대해서는 참조 값을 저장하는 것이 아니라 실제 값을 stack에 직접 저장
- 전역변수가 아닌 지역변수가 특정 함수 내에서 Stack에 할당 된 경우, 해당 지역변수는 다른 함수에서 접근할 수 없음
- 각 Thread 는 자신만의 stack 영역 할당
- 스레드 하나가 새롭게 생성되는 순간 해당 스레드를 위한 stack 도 함께 생성
- 각 스레드에서 다른 스레드의 stack 영역에는 접근할 수 없음
Heap
- Heap 영역에는 주로 긴 생명주기를 가지는 데이터들이 저장
- 대부분의 오브젝트는 크기가 크고, 서로 다른 코드블럭에서 공유되는 경우가 빈번
- 모든 Object 타입(Integer, String, ArrayList, ...)은 heap 영역에 생성
- 스레드의 개수와는 상관없이 단 하나의 heap 영역만 존재
- Heap 영역에 있는 오브젝트들을 가리키는 레퍼런스 변수가 stack에 저장
JVM 메모리 구조
기본 구조
Class Loader
- JVM 내로 클래스 파일을 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈
- 런타임 시에 동적으로 클래스를 로드
Execution Engine
- 클래스 로더를 통해 JVM 내의 Runtime Data Area에 배치된 바이트 코드를 명렁어 단위로 읽어서 실행
- 최초 JVM이 출시된 당시에는 인터프리터 방식이었기때문에 속도가 느리다는 단점이 있었지만 JIT 컴파일러 방식을 통하여 보완
- JIT는 바이트 코드를 어셈블러 같은 네이티브 코드로 바꿈으로써 실행이 빠르지만 역시 변환하는데 비용이 발생
- 위와 같은 이유로 JVM은 모든 코드를 JIT 컴파일러 방식으로 실행하지 않고, 인터프리터 방식을 사용하다가 일정한 기준이 넘어가면 JIT 컴파일러 방식으로 실행
Garbage Collector
- Garbage Collector(GC)는 힙 메모리 영역에 생성된 객체들 중에서 참조되지 않은 객체들을 탐색 후 제거하는 역할
Runtime Data Area
- JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역
- 크게 Method Area, Heap Area, Stack Area, PC Register, Native Method Stack로 구분
Method Area(Class Area)
- 모든 쓰레드가 공유하는 메모리 영역
- 메소드 영역은 클래스, 인터페이스, 메소드, 필드, Static 변수 등의 바이트 코드를 보관
- JVM이 동작해서 클래스가 로딩될 때 생성
Heap Area
- 모든 쓰레드가 공유하며, new 키워드로 생성된 객체와 배열이 생성되는 영역
- 메소드 영역에 로드된 클래스만 생성이 가능
- Garbage Collector의 주요 대상
- Garbage Collector가 참조되지 않는 메모리를 확인하고 제거하는 영역
- 효율적인 Garbage Collector를 위한 메모 리 분리
- 런타임시 할당
Stack Area
- 메서드 호출 시마다 각각의 스택 프레임(그 메서드만을 위한 공간)이 생성
- 메서드 안에서 사용되는 값들을 저장하고, 호출된 메서드의 매개변수, 지역변수, 리턴 값 및 연산 시 일어나는 값들을 임시로 저장
- 메서드 수행이 끝나면 프레임별로 삭제
- 컴파일 타임 시 할당
PC register
- 쓰레드가 시작될 때 생성되며, 생성될 때마다 생성되는 공간으로 쓰레드마다 하나씩 존재
- 쓰레드 실행에 대한 기록을하는 부분으로 현재 수행중인 JVM 명령의 주소 포함
Native Method Stack
- 스레드에서 네이티브 방식의 메소드가 실행되는 경우 쌓이는 영역
- 일반적인 메소드를 실행하는 경우 JVM 스택에 쌓이다가 해당 메소드 내부에 네이티브 방식을 사용하는 메서드(예를 들면 C/C++언어로 작성된 메서드)가 있다면 해당 메서드는 네이트브 스택에 저장
출처 및 참고