💻 [Java] 자바의 실행 프로세스 완전 정복 - 컴파일부터 JVM 메모리까지
2025. 8. 7. 10:25

🎯 개요

Java 프로그램은 단순히 .java 파일을 실행하는 것처럼 보이지만, 실제로는 JDK -> 컴파일러 -> JVM -> 메모리 영역 -> 실행 엔진에 이르기까지 여러 단계를 거쳐 실행됩니다.
이 글에서는 Java 실행 구조를 컴파일 시점부터 실행 시점까지 전체 흐름으로 정리해보았습니다.


✅ 주요 실행 흐름 요약

단계 설명
1. 작성 개발자가 .java 파일을 작성
2. 컴파일 javac(JDK 내 컴파일러)가 .class 바이트코드로 변환
3. 클래스 로딩 JVM의 ClassLoader가 .class 파일을 메모리로 로딩
4. 메모리 배치 JVM 런타임 메모리 영역(Method Area, Heap, Stack 등) 배치
5. 실행 엔진 처리 바이트코드를 인터프리터 또는 JIT 컴파일러로 실행
6. 결과 출력 프로그램 실행 결과가 콘솔 또는 UI로 출력

 


1. .java.class 컴파일 과정

// HelloWorld.java
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
}

 

작성된 자바 코드는 다음 명령으로 컴파일 됩니다:

javac HelloWorld.java
  • javac는 JDK(Java Development Kit)에 포함된 컴파일러
  • .java -> .class 바이트코드 생성
  • 이 .class 파일은 JVM이 이해할 수 있는 코드

2. JVM 구조와 실행 흐름

.class 파일이 만들어졌다면 이제 JVM이 실행을 맡습니다.

JVM 내부 주요 구성

구성 요소 설명
ClassLoader .class 파일을 JVM 메모리로 로드
Runtime Data Area 실행 시 필요한 메모리 공간
Execution Engine 바이트코드 해설/실행 (인터프리터 + JIT)
Native Interface C/C++로 작성된 라이브러리와 연결
Native Method Library OS 기반 라이브러리 집합

출처: https://inpa.tistory.com/


3. ClassLoader의 로딩, 링크 초기화

JVM의 클래스로더는 다음 3단계로 클래스를 처리합니다.

단계 설명
로딩(Loading) .class 파일을 메모리에 로드
링크(Linking) 검증(Verify): 유효한 바이트코드인지 검사
준비(Prepare): static 변수 공간 확보 및 기본값 설정
해결(Resolve): 심볼릭 레퍼런스를 실제 메모리 주소로 변경
초기화(Initialization) static 블록 및 변수 초기화 코드 실행

 

출처: https://inpa.tistory.com/


4. JVM 메모리 구조

클래스가 로딩되면 JVM 메모리에 다음과 같이 배치됩니다:

메모리 영역 설명
Method Area 클래스의 메타데이터, static 변수, 상수 정보
Heap 객체(instance), 배열 등이 저장됨
Stack 메서드 호출 시 생성되는 프레임 (지역 변수, 매개변수, 리턴주소 등)
PC Register 현재 실행 중인 JVM 명령의 주소 저장
Native Method Stack C/C++ native 메서드 호출 정보 저장

- 참고: Java 8 이후 PermGen이 제거되고 Metaspace가 Method Area를 대체

출처: https://inpa.tistory.com/


5. Execution Engine 처리

JVM은 바이트코드를 실행하기 위해 다음 두 가지 엔진을 사용합니다:

  • 인터프리터: 한 줄씩 해석하며 실행 -> 빠르게 시작되나 느림
  • JIT(Just-In-Time) 컴파일러: 반복 실행되는 코드를 네이티브 코드로 변환 -> 성능 최적화
  • 즉, 자바는 초기에 느릴 수 있지만 실행 중 JIT가 성능을 점차 개선합니다.

https://hyeinisfree.tistory.com/26#JIT%20%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC-1-6


최종 실행 흐름 요약

https://inpa.tistory.com/

1. HelloWorld.java (작성)
        ↓
2. javac 컴파일
        ↓
3. HelloWorld.class (바이트코드 생성)
        ↓
4. JVM 시작
        └─ ClassLoader → MethodArea/Heap/Stack에 클래스 배치
        └─ Execution Engine → 바이트코드 해석/실행
        ↓
5. 출력: Hello, world!

실무에서 중요하게 느낀 점

  • 클래스 로딩 순서JVM 메모리 구조를 이해하면, static 초기화, 메모리 누수, GC 최적화 같은 이슈를 더 쉽게 해결할 수 있었습니다.
  • 특히 Spring, Hibernate 등은 내부적으로 ClassLoader와 Reflection을 활용하므로 JVM의 이 구조가 매우 중요하게 작용합니다.

 

함께 보면 좋은 글: