JVM(Java Virtual Machine)이란?
- 자바 가상 머신 JVM(Java Virtual Machine)은 자바 프로그램 실행환경을 만들어 주는 소프트웨어이다. 자바 코드를 컴파일하여 .class 바이트 코드로 만들면 이 코드가 자바 가상 머신 환경에서 실행된다. JVM은 자바 실행 환경 JRE(Java Runtime Environment)에 포함되어 있고. 현재 사용하는 컴퓨터의 운영체제에 맞는 자바 실행환경 (JRE)가 설치되어 있다면 자바 가상 머신이 설치되어 있다는 뜻이다.
자바 가상 머신(JVM)의 동작 방식
- 자바로 개발된 프로그램을 실행하면 JVM 은 OS로 부터 메모리를 할당한다.
- 자바 컴파일러(javac)가 지바 소스코드를 자바 바이트코드(.class)로 컴파일 한다.
- Class Loader를 통해 JVM Runtime Data Area로 로딩한다.
- Runtime Data Area 에 로딩 된 .class 들은 Execution Engine 을 통해 해석한다.
- 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 수행하며 이 과정에서 Exectuion Engine에 의해 GC의 작동과 스레드 동기화가 이루어진다.
Runtime Data Area
- JVM(Java Virtual Machine)의 Runtime Data Area(실행 시간 데이터 영역)은 JVM이 프로그램을 실행하는 동안 데이터를 저장하고 관리하는 메모리 영역이다.
Runtime Data Area의 영역
- Method Area (메소드 영역) :
- 클래스 정보의 바이트 코드, 정적 변수(static 변수), 상수, 메소드 코드 등의 데이터를 저장한다. 모든 스레드가 공유하는 영역이며, JVM이 시작될 때 생성되어 프로그램이 종료될 때까지 유지된다.
- Heap (힙 영역) :
- 동적으로 생성된 객체 인스턴스와 배열이 할당되는 공간으로 가비지 컬렉션의 대상이며, 자동 메모리 관리 기능을 제공한다. 객체의 생성과 소멸이 이루어지는 영역이다.
- Stack (스택) :
- 각 스레드마다 개별적으로 생성되며, 메소드 호출 시 메소드의 로컬 변수, 매개변수, 임시 데이터 등을 저장된다. 메소드 호출 시 스택 프레임이 생성되고, 메소드 실행이 완료되면 해당 프레임이 스택에서 제거된다.
- PC Register (프로그램 카운터 레지스터) :
- 현재 실행 중인 명령어의 주소를 저장한다. 스레드마다 별도로 유지되며, 다음에 실행할 명령어의 위치를 지정한다..
- Native Method Stack (네이티브 메소드 스택) :
- Java 코드가 아닌 다른 언어로 작성된 네이티브 메소드를 실행하기 위한 스택으로 일반적으로 Java 언어로 작성된 메소드가 아닌 시스템 라이브러리 등의 메소드를 실행하는 데 사용한다.
클래스 로더 (Class Loader)
- 프로그램이 실행 중인 런타임에서야 모든 코드가 자바 가상 머신과 연결되는데 이렇게 동적으로 클래스 로딩해주는 역할을 하는 것이 클래스 로더이다.
클래스 로더의 종류
- 부트스트랩 클래스 로더(Bootstrap Class Loader):
- JVM 시작 시 가장 최초로 실행되는 클래스 로더
- 자바 클래스를 로드할 수 있는 자바 자체의 클래스 로더와 최소한의 자바 클래스만 로드
- 확장 클래스 로더(Extension Class Loader):
- 부트스트랩 클래스 로더를 부모로 갖는 클래스 로더, 확장 자바 클래스들을 로드
- jre/lib/ext에 있는 클래스 파일을 로드
- 시스템 클래스 로더(System Class Loader):
- 자바 프로그램 실행 시 지정한 Classpath 에 있는 클래스 파일 혹은 jar에 속한 클래스들을 로드
클래스 로더 3가지 원칙
- 위임 원칙 : 클래스 로더는 클래스 또는 리소스를 찾기 위해 요청을 받았을 때, 상위 클래스 로더에게 책임을 위임하는 위임 모델을 따른다.
- 가시 범위 원칙 : 하위 클래스 로더는 상위 클래스 로더가 로드한 클래스를 볼 수 있지만, 반대로 상위 클래스 로더는 하위 클래스 로더가 로드한 클래스를 알수없다.
- 유일성의 원칙 : 하위 클래스 로더가 상위 클래스 로더에게 로드한 클래스를 다시 로드하지 않아야 한다.
Execution Engine(실행 엔진)
- JVM(Java Virtual Machine)의 핵심 구성 요소 중 하나로, Java 프로그램을 실제로 실행하는 역할을 담당한다. 실행 엔진은 JVM의 Runtime Data Area에 저장된 bytecode(바이트 코드)를 읽고 해석하여 명령어를 실행한다.
Exection Engine 방식
- Interpreter(인터프리터):
- 인터프리터 방식은 bytecode를 한 줄씩 읽어 해석하고, 해당 명령어를 직접 실행한다. 인터프리터는 빠른 시작 속도를 가지지만, 명령어 하나씩 해석하고 실행하는 과정에서 반복적인 작업이 필요하여 실행 속도가 상대적으로 느릴 수 있다.
- Just-In-Time Compilation(JIT 컴파일):
- JIT 컴파일은 인터프리터의 단점을 보완하기 위해 도입된 기술로 JIT 컴파일러는 bytecode를 보다 효율적인 기계어로 번역하여 실행한다. 초기에는 인터프리터로 실행하면서 코드를 분석하고, 자주 실행되는 부분을 식별하여 해당 부분을 기계어로 변환한다. 그리고 나서 변환된 기계어로 직접 실행함으로써 인터프리터에 비해 빠른 실행 속도를 제공한다.