오늘은 자바의 JVM(Java Virtual Machine) 에 대해 알아보자 !
위 자료는 자바 심화 04강 영상을 토대로 작성되었습니다.

자바의 동작 과정을 한 단계씩 설명하겠습니다.
1. Source Code 작성 (Source.java)
개발자가 자바 프로그래밍 언어로 .java 파일을 작성합니다.
코드에는 클래스와 메서드, 변수 등을 선언하며, 자바 표준 문법에 맞춰 작성해야 합니다.
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
2. Compilation (컴파일 단계)
- 자바 컴파일러(javac)가 소스 코드(Source.java)를 바이트코드로 변환합니다.
- 바이트코드는 .class 파일로 저장되며, 이 파일은 플랫폼 독립적인 중간 코드입니다.
- 바이트코드는 개발자가 읽을 수 있는 형태가 아니라, JVM이 해석 가능한 명령어들로 구성되어 있습니다.
컴파일 과정 예:
bash
javac HelloWorld.java
이 명령은 HelloWorld.class라는 바이트코드 파일을 생성합니다.
3. Class Loader (클래스 로더)
JVM이 실행될 때, 필요에 따라 .class 파일을 메모리에 로드하는 역할을 합니다.
주요 기능:
- 로딩 (Loading): 프로그램 실행 시 필요한 .class 파일을 JVM에 로드.
- 연결 (Linking): 클래스 간의 참조를 검증하고 링크를 설정.
예: 메서드 호출 시 어떤 클래스의 메서드인지 확인.
- 초기화 (Initialization): 정적 변수 및 정적 초기화 블록을 실행.
클래스 로더는 필요한 클래스만 로드하며, 프로그램이 실행 중일 때도 동적으로 로드할 수 있습니다.
4. Runtime Data Area (런타임 데이터 영역)
- JVM이 실행 중에 사용하는 메모리 영역으로, 여러 하위 영역으로 나뉩니다:
Static Area (정적 영역):
- 클래스 메타데이터(클래스 이름, 메서드 정보, 정적 변수 등)를 저장합니다.
- 프로그램 내 모든 스레드에서 공유됩니다.
Heap (힙):
- 모든 객체와 인스턴스 변수가 저장됩니다.
- 가비지 컬렉터가 불필요한 객체를 정리하여 메모리 관리를 담당합니다.
Stack (스택):
- 각 스레드마다 별도로 생성됩니다.
- 메서드 호출 시 생성되는 지역 변수와 메서드 매개변수가 저장됩니다.
- 스택은 LIFO(Last In, First Out) 구조로 동작합니다.
PC Register (프로그램 카운터):
- 각 스레드가 실행 중인 명령의 주소를 저장합니다.
- JVM이 여러 스레드를 관리할 때 사용됩니다.
Native Method Stack (네이티브 메서드 스택):
- 네이티브 코드(C, C++ 등)를 실행할 때 사용됩니다.
- 예: 운영 체제와 직접 상호작용.
5. Execution Engine (실행 엔진)
- JVM 내에서 바이트코드를 실제 실행하는 핵심 구성 요소입니다.
작동 방식:
인터프리터 (Interpreter):
- 바이트코드를 한 줄씩 읽고 실행합니다.
- 간단하지만, 실행 속도가 느립니다.
JIT 컴파일러 (Just-In-Time Compiler):
- 자주 실행되는 코드(Hotspot)를 네이티브 코드로 변환하여 속도를 높입니다.
- 네이티브 코드로 변환된 코드는 JVM 없이도 실행 가능.
- 실행 엔진은 인터프리터와 JIT 컴파일러를 병행하여 성능을 최적화합니다.
6. Garbage Collector (GC)
JVM 내 힙 영역에서 더 이상 참조되지 않는 객체를 자동으로 정리합니다.
주요 특징:
- 개발자가 직접 메모리를 해제할 필요가 없습니다.
- 다양한 GC 알고리즘(Generational GC, G1 GC 등)을 통해 성능 최적화.
String unused = new String("Garbage");
unused = null; // 참조를 해제하면 GC가 메모리를 정리
7. Native Method
- JVM이 자바 외부의 네이티브 코드와 상호작용해야 할 때 사용됩니다.
- 예를 들어, 운영 체제 함수 호출, 네이티브 라이브러리(C, C++ 등) 호출 등이 포함됩니다.
- 자바는 JNI(Java Native Interface)를 통해 네이티브 코드를 호출할 수 있습니다.
전체 과정의 흐름 요약
- 개발자는 .java 소스 파일을 작성합니다.
- 자바 컴파일러(javac)가 .java 파일을 .class 바이트코드로 변환합니다.
- JVM의 클래스 로더가 .class 파일을 메모리에 로드합니다.
- 실행 엔진이 바이트코드를 실행하며, 필요한 메모리를 런타임 데이터 영역에서 관리합니다.
- 가비지 컬렉터가 불필요한 객체를 정리하여 메모리 누수를 방지합니다.
JVM의 각 단계는 자바 프로그램이 플랫폼 독립성과 안정성을 유지하며 동작할 수 있도록 지원합니다.