우당탕탕 개발_𝒍𝒐𝒈

JVM 실행 과정/구성 요소 본문

대외 활동/데브코스

JVM 실행 과정/구성 요소

hojeong01 2024. 7. 17. 22:24

JVM(Java Virtual Machine)은  자바 바이트 코드(. class 파일)를 실행할 수 있는 가상컴퓨터이다.

 

자바의 핵심 철학인 '한 번 작성하면 어디서든 실행된다'를 실현할 수 있는 JVM은 자바 애플리케이션을 운영체제와 하드웨어로부터 독립적으로 실행할 수 있게 해 주며 메모리 관리, GC, 스레드 관리 등 자바 프로그램의 실행환경을 제공한다. 

 

그럼 JVM의 전체적인 구성을 그림으로 먼저 보고 

차근 차근 알아보는 시간을 가져보자

 

 

1. JVM 동작 방식

JVM 동작 방식을 간단히 요약하자면 아래와 같이 요약할 수 있다.

  • 자바 컴파일러가(javac) 자바 소스 코드를 바이트 코드로 컴파일합니다. 
  • JVM 속으로 클래스 파일을 동적으로 로드 후 링크를 통해 메모리 영역에 배치 한다. 
  • Runtime Data Area에 로딩된 코드는 실행 엔진을 통해 해석한다. 이 과정에서 GC와 스레드 동기화가 이루어진다.

사실 이때까지만해도 어렵긴 해도 의외로 간단하네 할 수 있겠지만.. 상세히 들어갈 수 록 복잡해지는 느낌을 받을 것이다. 

그래도 천천히 내용을 따라가다보면  

한낱 문과인 나도 이해 했으니 당신들은 더 쉽게 이해할 수 있을 거다...

 

그럼 본격적으로 JVM에 대해 더욱 상세히 알아보자 

 


2. 정적 컴파일 (Static compilation)

 

우선 소스 코드로 되어있는. java 파일을 컴파일러를 통해 바이트 코드로 변환 후. class 파일로 저장하는 과정이 필요하다. 

이때.'javac' 컴파일러가 java파일의 소스 코드를 한 번에 읽어 바이트 코드로 변환하는데 이 방식을 정적 컴파일(static compilation)이라고 한다. 

 

이렇게 컴파일된 바이트 코드는 JVM에 의해 실행되게 된다. 


3.Class Loader (클래스 로더)

 

JVM의 클래스 로더에 대해 쉽게 설명하자면

프로그램이 실행 중에 필요한 클래스를 찾아서 메모리에 불러오고(동적 로드), 프로그램이 그 클래스를 사용할 수 있도록 연결하고 준비하는 역할을 한다(링크를 통한 배치).

 

굳이 굳이 현실 세계와 비유하자면 

도서관 사서 = jvm 

도서관의 모든 책들 =class로 가정할 때 

내가 사서에게 특정 책이 필요하다고 이야기하고(프로그램 실행 중 필요한 클래스)

사서가 그 책을 찾아와 나에게 건네어준 후(동적 로드)

책의 내용을 이해할 수 있도록 필요한 부분에 책갈피를 끼워 (링크를 통한 배치) 도와주는 과정으로 설명할 수 있을 것 같다.

 

클래스 파일의 로딩 순서는 3단계로 구성된다. 

Loding -> Linking -> Initializing

 

  • Loding : 자바 클래스 파일을 메모리에 로드한다
  • Linking : 클래스 파일을 사용하기 위한 검증 단계
Verification (검증) 클래스 파일이 손상되거나 해킹된 것은 아닌지 코드가 JVM에서 안전하게 실행될 수 있는지를 검토
Preparation (준비) 프로그램에서 사용된 정적 변수에 필요한 메모리를 할당하고 초기값을 기본값으로 설정
Preparation (해결) 프로그램에서 사용될 변수, 메서드, 클래스 등의 이름을 실제로 메모리 어디에 있는지 찾아 연결
(ex :  네비게이션에 '친구집' 입력하지 않고 친구 집의 실제 주소를 입력하는 것)

 이 단계를 통해 JVM은 클래스를 안전하고 효율적으로 실행할 수 있도록 준비한다.

  • Initializing(초기화) :  클래스 변수들을 적절한 값으로 초기화한다. 

이 문장만 보면 Preparation에서 초기값을 설정하는 거 아니었어??라고 헷갈릴 것이다! 아니면 너무너무 멋지다. 

아무튼 헷갈린 사람들을 위해 Preparation과 Initializing 단계를 비교해 보겠다.

    static int a; // Preparation 단계에서 a는 0으로 설정됨
    static int b = 5; // Initialization 단계에서 b는 5로 설정됨

    static {
        a = 10; // Initialization 단계에서 a= 10으로 재설정
        b = 20; // Initialization 단계에서 b= 20으로 재설정
    }

즉 Preparation는 실제 코드에 명시된 초기값이 아니라 데이터 타입의 기본값을 할당하는 것이고 

Initializing은 정적 변수에 사용자 정의 초기값 설정 및 static블록을 실행하며 필요한 초기화 작업을 수행하는 것이라고 볼 수 있다. 

 

이렇게 클래스 로더에 의해 로딩된 바이트 코드는 런타임 데이터 영역( Runtime Data Area )에 배치된다.


4.Execution Engine(실행엔진) 

실행 엔진은 클래스 로더에 의해 런타임 데이터 영역에 배치된 바이트 코드를 읽어 기계가 실행할 수 있는 형태로 변환한다. 이때 실행엔진은 인터프리터와 JIT (Just In Time) 컴파일러 두 가지 방식을 혼합하여 바이트 코드를 실행한다.

 

<작동 원리>

  • InterPreter (인터프리터)

바이트 코드를 한 줄씩 읽고 즉시 실행하는 방식이다. 실행 초기 단계에서는 빠르게 시작할 수 있다는 장점이 있지만 

한 줄씩 해석하고 실행하기 때문에 반복되는 코드에서는 비효율적이고 실행 속도가 느릴 수 있다는 단점이 있다. 

 

  • JIT 컴파일러

프로그램 실행 초기에 인터프리터가 바이트 코드 한 줄씩 읽어 실행하며 메서드의 실행 빈도를 체크한다.

이때 자주 발생하는 메서드를 기계어로 변환하여 캐시에 저장 후 동일한 메서드가 호출될 때 인터프리터가 읽는 것이 아닌 변환된 기계어가 빠르게 실행되는 방식이다.

 

자주 실행되는 코드가 빠르게 실행되므로 전체 프로그램 실행 속도가 향상되지만 JIT 컴파일러 자체가 시간이 걸려 컴파일링에서 약간의 지연이 발생할 수 있다. 

 

간단한 코드로 예시를 들어보자면 

 public static void main(String[] args) {
        for (int i = 0; i < 10000; i++) {
            printHello();
        }
    }

    public static void printHello() {
        System.out.println("Hello, World!");
    }

 반복문을 통해 printHello()를 10000번 호출한다고 할 때 초기에는 인터프리터가 printHello()를 한 줄씩 읽고 실행한다. 

이때 JVM이 printHello() 메서드가 자주 실행된다는 것을 기록하면(프로파일링 작업) 이후 JIT 컴파일러가 이 메서드를 기계어로 변환하여 캐시에 저장합니다. 

따라서 이후   printHello()가 또 호출되었을 때 인터프리터 없이  캐시에 저장된 기계어로 빠르게 실행된다. 

 

이렇게 JVM은 인터프리터와 JIT 컴파일러를 함께 사용함으로써 자바 프로그램의 실행 속도를 효율적으로 관리할 수 있다. 

 

메모리 영역에서 더 이상 사용하지 않는 메모리를 자동으로 회수해 주는 가비지 컬렉터에 대해서는 따로 정리하여 링크로 올려둘 예정이다. 그 이유는 GC에 대한 내용을 조금 더 자세히 설명해 주기 위해서이다.

 


5. Runtime Data Area

마지막으로 런타임 데이터 영역에 대해 알아보자 

Runtime Data Area은 자바 애플리케이션을 실행하기 위해 운영체제로부터 할당받은 메모리 공간이다. 

즉 바이트코드가 수행되는 공간 

 

메서드영역, 힙, 스택, 프로그램 카운터, 네이티브 메서드 스택으로 구성되어 있으며 

더 추가적인 내용은 지난번에 올린 JVM 메모리 구조 포스팅을 참고하자!

 

 

 

2024.02.13 - [𝐬𝐭𝐮𝐝𝐲/𝐉𝐚𝐯𝐚] - 메서드 영역, 스택 영역, 힙 영역(JVM)


강사님이 자바의 플랫폼 사진을 보여주셨는데 

JVM이 눈에 띄어 혼자서 더 공부하게 되었다. 

처음 구글링을 할 때 이렇게까지 내용이 방대할 줄 몰랐지만 내가 사용하는 언어가 어떻게 작동되는지는 알고 사용하고 싶은 마음에 포기할 수 없었다.

나처럼 공부를 시작한 지 얼마 안 된 분 들을 위해 최대한 예시도 들고 단어도 풀어가며 설명했는데 

도움이 되었을지는 모르겠지만 다들 파이팅이다!!