JVM 구동 방식
컴파일 - Compile Time
.java 파일로 작성한 소스 코드를 JVM이 이해할 수 있는 중간 언어로 바꾸는 단계 자바 컴파일러 (javac)가 바이트코드(Bytecode)라는 중간 언어로 번역. 이 결과물이 .class 파일이다.
바이트코드 : 특정 컴퓨터 하드웨어에 종속되지 않는 JVM이라는 가상 머신이 이해할 수 있는 형식이다.
.class 파일을 가지고 실행(Runtime)을 가진다.
클래스 로더 (Class Loader) : JVM이 시작되면 먼저 필요한 . class 파일들을 찾아 JVM 메모리 영역 (Runtime Data Area)로 불러오는 작업을 한다.
실행 엔진 (Execution Engine) : 불러온 바이트코드를 실제로 진행하는 JVM의 핵심 부품이다. 이 실행 엔진 안에서 인터프리터와 JIT 컴파일러가 협력한다.
인터프리터 : 바이트 코드를 '한 줄씩' 읽어서 그때그때 컴퓨터의 실제 기계어로 번역하고 실행한다. 프로그램 실행의 초반이나, 자주 실행되지 않는 코드는 인터프리터가 담당한다.
JIT 컴파일러: JVM이 바이트코드를 실행하는 동안, 실행 빈도 등을 프로파일링하다가 자주 실행되는 코드 블록을 발견하면, JIT 컴파일러가 나선다. 컴퓨터의 실제 CPU가 이해하는 고도로 최적화된 '기계어 코드'로 통째로 컴파일한다. 반복되는 로봇 지시는 숙력된 전문가가 가장 효율적인 기계어로 자동화 시켜둔다.
Runtime Data Area (JVM 메모리 영역) : 프로그램 실행 중에 필요한 데이터들 (힙, 스택 , 메소드 영역 등)이 저장되는 공간이다.
JVM의 핵심 구성 요소
클래스 로더 서브시스템 (Class Loader Subsystem):
JVM이 시작될 때나 실행 중에 필요한 클래스를 동적으로 로딩하는 역할을 한다.
로딩(Loading): class 파일을 읽어서 바이트코드를 가져와서 JVM 메모리의 '메서드 영역'에 저장한다. 클래스 이름,부모 클래스, 메서드 정보, 변수 정보와 같은 것들이 이때 저장된다. 그리고 이 .class 파일을 표현하는 Class 타입의 객체를 힙(Heap) 메모리에 생성한다. 이때 Class 타입의 객체란 추후 리플렉션(Reflection)이라는 기술에 사용되는 클래스 메타데이터 정보를 저장해두는 것으로 알아두자.
링크(Linking): 로딩된 클래스들이 서로 잘 연결되어 있는지 확인하는 단계다. 검증(Verification), 준비(Preparation), 분석(Resolution) 과정을 거친다.
초기화(Initialization): 클래스 변수들을 초기화하고, static 블록 같은 초기화 코드를 실행한다.
JVM 메모리 영역(JVM Memory Areas):
JVM이 프로그램을 실행하기 위해 사용하는 메모리 공간이다. 여러 영역으로 나뉘어 있다.
메서드 영역(Method Area) : 클래스 정보(클래스 이름, 메서드, 변수, static 변수 등)을 저장하는 공유 영역이다.
힙 영역(Heap Area): 모든 객체들이 생성되고 저장되는 공유 영역이다. 네가 new 키워드로 객체를 만들면 여기가 저장돼. Garbage Collector가 주로 여기서 작동한다.
스택 영역(Stack Area): 각 스레드마다 독립적으로 생성되는 영역이다. 메서드가 호출될 때마다 '스택 프레임' (Stack Frame)이라는 공간이 생기고, 그 안에 메서드의 지역 변수, 파라미터, 중간 계산 결과 같은 것들이 저장된다. 메서드 실행이 끝나면 해당 스택 프레임은 사라진다.
PC 레지스터 (PC Registers) : 각 스레드마다 독립적으로 생성되고, 현재 스레드가 실행하고 있는 JVM 명령어의 주소를 저장한다.
네이티브 메서드 스택(Native Method Stacks) : 각 스레드마다 독립적으로 생성되고, 자바 코드가 아닌 C/C++ 등으로 작성된 네이티브 메서드의 정보를 저장한다.
실행 엔진(Execution Engine):
바이트코드를 실제로 실행하는 역할을 한다.
인터프리터(Interpreter) : 바이트 코드를 한 줄씩 일거서 바로 실행한다. 단순하지만 같은 코드를 반복해서 읽으면 비효율적일 것이다.
JIT 컴파일러 (Just-In-Time Compilier) : 인터프리터의 비효율성을 개선하기 위해 등장했다. 자주 실행하는 코드(핫스팟, Hotspot) 블록 전체를 네이티브 코드로 컴파일해 둬서, 다음번에 같은 코드가 나오면 다시 해석할 필요 없이 컴파일된 빠른 네이티브 코드를 바로 실행하게 해준다.
가비지 컬렉터 (Garbage Collector) : 힙 영역에서 더 이상 사용되지 않는 (어떤 변수도 참조하지 않는) 객체들을 자동으로 찾아내서 메모리를 회수하는 역할을 한다. 개발자가 메모리 관리에 신경 쓰지 않게 해주는 자바의 큰 장점 중 하나이다.
자바 네이티브 인터페이스 (Java Native Interface - JNI):
자바 코드(바이트코드)가 C, C++ 같은 네이티브 언어로 작성된 라이브러리를 호출하거나, 반대로 네이티브 코드에서 자바 코드를 호출할 수 있도록 연결해 주는 인터페이스야. 운영체제나 하드웨어에 특화된 기능을 자바에서 사용할 때 필요해.
네이티브 메서드 라이브러리
JNI를 통해 호출되는 C, C++ 등으로 작성된 실제 네이티브 코드 라이브러리들의 모음이야.

Last updated
