JVM이 무엇이고 구조에 대해 알아보자
JVM (Java Virtual Machine) = 자바 가상 머신
자바 코드를 컴파일 해서 .class 바이트 코드로 만들면 해당 코드는 JVM 환경에서 실행된다.
JVM의 이점
C언어와 비교해보았을 때, C언어로 작성된 Test.c 소스 코드를 컴파일 할 때 운영체제에 따른 각각의 컴파일러를 적용시켜야 한다. 예를 들어 Test.c 소스 코드를 윈도우 운영체제 환경에서 컴파일 할 때는 윈도우 컴파일러를 사용해야하며, 리눅스 환경에서 컴파일을 할 때는 리눅스 컴파일러를 사용해야 한다.
하지만 Java는 운영체제 환경과 상관 없이 통합된 자바 컴파일러를 사용할 수 있다. 윈도우, 리눅스와 같은 서로 다른 운영체제여도 컴파일을 할 때는 동일한 하나의 자바 컴파일러를 이용해서 자바코드(Test.java)를 바이트 코드(Test.class)로 컴파일한다.
바이트 코드
사람이 작성한 자바 코드(Test.java)에서 컴퓨터가 읽는 기계어로의 중간 단계의 코드
컴파일된 바이트 코드(Test.class)는 각자의 플랫폼에 설치되어 있는 자바 가상 머신(JVM) 을 통해 운영체제에 맞는 실행 파일로 바뀐다. 윈도우 운영체제의 경우 윈도우 자바 가상머신, 리눅스의 경우 리눅스 자바 가상머신을 각각 이용해서 실행 파일로 변환이 된다.
즉, Java는 플랫폼에는 종속적이지는 않지만 JVM은 플랫폼에 의존적이다.
실행 과정

- Test.java 코드를 사람이 직접 작성한다.
- 자바 컴파일러(javac)에 컴파일 명령을 내리면 Test.class 파일이 만들어진다.
- 만들어진 바이트 코드(Test.class) 는 클래스 로더를 통해 JVM Runtime Area로 로딩된다.
- 로딩된 바이트 코드는 설치된 JVM에 가게 되고 프로그램이 실행될 때마다 JVM이 즉각 기계어로 해석한다.
JVM이 바이트 코드를 해석하는 방법
- Interpreter 방식
- 바이트 코드를 한줄씩 해석하고 실행하는 방식
- 속도가 느리다
- JIT(Just In Time) 방식
- Interpreter의 느린 단점을 보완하기 위한 방식
- 바이트 코드를 실제 실행하는 시점에 각 OS에 맞는 Native Code로 바로 변환시킨다.
- 속도면에서는 개선되었지만 Native Code를 변환하는 과정에서 비용이 발생하므로 Interpreter 방식을 사용하다가 일정 기준을 넘어갈 시에 JIT 방식을 활용한다.
- JIT는 실행할 때 컴파일을 하면서 코드를 캐싱하기 때문에 추후 다른 코드를 실행할 때도 바뀐 부분만 컴파일하고 나머지는 캐싱된 코드를 사용한다.
JVM의 구조

Class Loader
실행되어야 할 클래스와 JVM을 연결시켜주는 역할을 한다.
자바 컴파일러를 이용해서 컴파일된 바이트 코드가 생성되는데 클래스 로더가 이를 받아 묶어서 Runtime Data Area로 적재된다.
Execution Engine
Runtime Data Area에 배치된 바이트 코드를 실행하는 모듈의 역할을 한다.
해당 실행 엔진은 바이트 코드를 명령어 단위로 읽어서 실행한다.
Garbage Collector
더는 사용하지 않는 메모리를 자동으로 회수해서 개발자가 따로 메모리를 관리하지 않아도 되게 한다.
Runtime Data Area 영역 안 Heap 메모리에 적재된 객체들중에 참조되지 않은 객체들을 탐색후 제거한다.
Runtime Data Area
JVM의 메모리 영역으로 자바 애플리케이션을 실행할때 사용되는 데이터를 적재한다.
- Heap Area
- new 키워드로 생성된 객체와 배열이 생성되는 영역
- Garbage Collector가 주기적으로 메모리를 제거하는 영역이다.
- 모든 스레드가 공유하는 영역
- Method Area
- 클래스 멤버 변수의 이름, 데이터 타입, 접근 제어자 정보와 같은 필드 정보
- 메서드 정보
- Constant Pool, static 변수, final class 등이 생성
- Garbage Collector가 주기적으로 메모리를 제거하는 영역
- JVM이 시작될 때 생성되는 공간으로 바이트 코드를 처음 메모리 공간에 올릴 때 초기화 되는 대상을 저장하는 메모리 공간
- 모든 스레드가 공유하는 영역
- Stack Area
- 지역 변수, 파라미터, 리턴 값, 연산에 사용되는 값 등이 생성
- 각 스레드마다 생성되는 개별 영역
- PC Register
- Thread가 생성될 때마다 생성되는 영역
- 스레드가 생성되는 부분의 주소와 명령 저장
- 현재 실행 중인 JVM 주소를 저장
- Native Method Stack
- 자바 외의 언어로 작성된 네이티브 코드를 실행할 때 사용
'Programming > Java' 카테고리의 다른 글
| Interface와 Abstract (1) | 2025.06.15 |
|---|---|
| 원시타입과 참조 타입 (2) | 2025.05.04 |
| 의존성에 대해서 (2) | 2025.03.20 |
| BufferedReader와 BufferedWriter (2) | 2025.02.15 |
| 객체지향에게 역할과 책임이란 (1) | 2025.02.11 |