자바는 "컴파일 언어"이면서 "인터프리터 언어"의 특성을 모두 가집니다.
이 글에서는 자바 소스 코드가 어떻게 실행 가능한 프로그램으로 변환되는지, 전체 컴파일 및 실행 과정을 단계별로 설명합니다.
1️⃣ 소스 코드 작성
개발자가 Hello.java 같은 자바 소스 파일을 만듭니다.
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, Java!");
}
}
2️⃣ javac 컴파일: 바이트코드 생성
자바 컴파일러(javac)가 소스 파일을 읽어 플랫폼 독립적인 바이트코드(.class)로 변환합니다.
내부적으로는 다음 네 단계를 거칩니다.
| 어휘 분석 | 소스 코드를 토큰(키워드, 연산자, 식별자 등) 단위로 분해 |
| 구문 분석 | 토큰을 AST(Abstract Syntax Tree)로 만들고 문법 오류 검사 |
| 의미 분석 | 타입 검사, 변수/메서드 존재 확인, import 해석 등 |
| 바이트코드 생성 | AST를 기반으로 JVM이 이해할 수 있는 .class 파일 생성 |
실행 명령어:
javac Hello.java # Hello.class 생성
생성된 Hello.class는 사람이 읽기 어렵지만, 아래 명령어로 바이트코드를 확인할 수 있습니다.
javap -c Hello
3️⃣ 클래스 로딩 (Runtime)
JVM(Java Virtual Machine)이 시작되면 클래스 로더(Class Loader)가 .class 파일을 메모리(Runtime Data Area)에 로드합니다.
- 로딩: 파일에서 바이트코드를 읽어옴
- 링크: 검증(바이트코드 안전성 확인) → 준비(static 변수 기본값 할당) → 해석(심볼릭 레퍼런스를 실제 주소로 변환)
- 초기화: static 블록 및 변수 초기화
4️⃣ 실행 엔진: 바이트코드 → 기계어
JVM 내부의 실행 엔진(Execution Engine)이 바이트코드를 실제로 실행합니다. 여기서 두 가지 방식이 사용됩니다.
- 인터프리터(Interpreter)
바이트코드를 한 줄씩 읽고 즉시 기계어로 변환하여 실행.
초기 속도는 느리지만 메모리 부담이 적음. - JIT 컴파일러(Just-In-Time Compiler)
반복 실행되는 코드(핫스팟, HotSpot)를 감지하여 네이티브 기계어로 컴파일하고 캐싱.
같은 코드는 다시 해석하지 않아 전체 실행 속도가 크게 향상됨. - (옵션) AOT 컴파일러(Ahead-Of-Time)
실행 전에 미리 네이티브 코드로 컴파일 (Java 9부터 실험적 도입, GraalVM에서 활용)
📊 전체 과정 흐름도 (텍스트 버전)
[ .java ] --javac--> [ .class ] --클래스 로더--> JVM 메모리
│
┌─────────────┴─────────────┐
│ 실행 엔진 │
│ ┌───────────────┐ │
│ │ 인터프리터 │ │
│ └───────┬───────┘ │
│ ▼ │
│ ┌───────────────┐ │
│ │ JIT 컴파일러 │ (핫스팟)│
│ └───────┬───────┘ │
│ ▼ │
│ 네이티브 기계어 실행 │
└───────────────────────────┘
🔍 자주 묻는 질문
Q1. 자바는 컴파일 언어인가 인터프리터 언어인가?
→ 둘 다 사용합니다. javac로 컴파일해서 바이트코드를 만들고, 실행 시 JVM이 인터프리트 + JIT 컴파일로 혼합 실행합니다.
Q2. .class 파일은 OS마다 다른가요?
→ 아닙니다. 같은 버전의 JVM이라면 어느 OS에서든 동일한 .class 파일이 실행됩니다. 이것이 자바의 "Write Once, Run Anywhere" 원리입니다.
Q3. JIT 컴파일의 장점은?
→ 반복 코드를 네이티브 코드로 바꿔 인터프리터보다 훨씬 빠릅니다. 서버용 장기 실행 프로그램에서 성능이 거의 C++ 수준으로 향상됩니다.
📚 마무리
자바 컴파일 과정은 단순히 javac로 끝나는 것이 아니라, JVM의 클래스 로딩과 실행 엔진(인터프리터 + JIT)까지 포함하는 전체 파이프라인입니다.
이 과정을 이해하면 자바 성능 튜닝, 바이트코드 조작, JVM 내부 동작을 더 깊이 있게 파악할 수 있습니다.
✍️ 본 포스트는 자바의 컴파일 및 실행 과정을 초보자도 이해하기 쉽게 정리했습니다.
궁금한 점이나 수정 요청은 댓글로 남겨주세요!
'면접복기' 카테고리의 다른 글
| (면접복기)자바 기본 타입(Primitive Type) 완벽 정리 (0) | 2026.05.15 |
|---|---|
| (면접복기)OCP를 준수하는 결제 시스템 확장하기: 전략패턴을 활용한 유연한 설계 (0) | 2026.01.27 |
| (면접복기)트랜잭션 격리 수준 (Transaction Isolation Levels) (0) | 2025.11.19 |
| (면접복기)쓰레드 풀 vs 커넥션 풀 (0) | 2025.11.19 |