본문 바로가기
  • 🕊️ A Piece of Peace
🖥️ PC/JAVA

2. JVM

by Moom2n 2024. 6. 24.

Java Virtual Machine(JVM)은 Java 애플리케이션을 실행하기 위한 가상 컴퓨터입니다. JVM은 Java 프로그램을 실행하는 데 필요한 환경을 제공합니다. JVM은 Java 프로그램을 바이트코드(bytecode)로 변환하여 실행하며, 이 바이트코드는 플랫폼 독립적이기 때문에 다양한 운영 체제에서 실행될 수 있습니다.

즉, OS 위에서 Java를 실행시킬 무언가가 "JVM"이다.

 

JVM의 동작 과정

  1. 소스 코드 컴파일: Java 소스 파일(.java)을 자바 컴파일러(javac)를 사용하여 바이트코드(.class)로 컴파일합니다. (.class) 바이트코드는 JVM이 이해할 수 있는 언어로 변환된 자바 소스코드이다.
  2. 클래스 로딩: Class Loader를 통해 바이트코드 파일을 메모리에 로드합니다.
  3. 바이트코드 실행: Execution Engine이 바이트코드를 해석하거나 컴파일하여 실행합니다. 이 과정에서 필요에 따라 JIT 컴파일러가 동작하여 바이트코드를 기계어로 변환합니다.
  4. 메모리 관리: Garbage Collector가 주기적으로 동작하여 사용되지 않는 객체를 메모리에서 해제합니다.

JIT 컴파일러란?

JIT 컴파일(just-in-time compliation) 또는 동적 번역(dynamic translation) 이라고 한다.

JIT 컴파일러는 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일러이다.

 

인터프리터 방식의 단점을 보완하기 위해 도입되었다.

인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 컴파일하여 기계어로 변경하고, 이후에는 해당 더 이상 인터프리팅 하지 않고 기계어로 직접 실행하는 방식이다.

 

기계어(컴파일된 코드)는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 빠르게 수행하게 된다.
물론 JIT 컴파일러가 컴파일하는 과정은 바이트 코드를 인터프리팅하는 것보다 훨씬 오래걸리므로 한 번만 실행되는 코드라면 컴파일 하지 않고 인터프리팅하는 것이 유리하다.

따라서 JIT 컴파일러를 사용하는 JVM들은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고 일정 정도를 넣을때에만 컴파일을 수행한다.

 

자바에선 자바 컴파일러가 자바 프로그램 코드를 바이트 코드로 변환한 다음,
실제 바이트 코드를 실행하는 시점에서 자바 가상 머신(JVM, 정확히는 JRE)이 바이트 코드를 JIT 컴파일을 통해 기계어로 변환한다.

 

 

JVM의 주요 구성 요소

  1. Class Loader(클래스 로더)
    • JVM 내에서 클래스를 로드하는 역할을 합니다. 클래스 파일을 읽어 메모리에 적재하고, 링크(Linking) 및 초기화(Initialization)를 수행합니다.
    • Class Loader는 애플리케이션 클래스 로더, 확장 클래스 로더, 부트스트랩 클래스 로더 등 여러 계층으로 구성됩니다.
  2. Runtime Data Areas(런타임 데이터 영역)
    • Method Area(메소드 영역): 클래스 수준의 정보(예: 클래스 이름, 메소드 정보, 변수 정보 등)을 저장합니다.
    • Heap(힙): 객체와 배열이 저장되는 공간입니다. Garbage Collector(가비지 수집기)가 힙 영역을 관리합니다.
    • Stack(스택): 각 스레드마다 존재하며, 메소드 호출과 관련된 지역 변수, 매개 변수, 반환 값, 중간 계산 결과 등이 저장됩니다.
    • PC Register(PC 레지스터): 각 스레드마다 존재하며 현재 실행 중인 JVM 명령의 주소를 저장합니다.
    • Native Method Stack(네이티브 메소드 스택): Java가 아닌 네이티브 코드(C, C++ 등)로 작성된 메소드가 실행될 때 사용되는 스택입니다.
  3. Execution Engine(실행 엔진)
    • Interpreter(인터프리터): 바이트코드를 한 줄씩 해석하고 실행합니다.
    • JIT Compiler(Just-In-Time 컴파일러): 자주 사용되는 바이트코드를 기계어로 컴파일하여 성능을 향상시킵니다.
    • Garbage Collector(가비지 수집기): 사용되지 않는 객체를 자동으로 메모리에서 제거하여 메모리 누수를 방지합니다.
  4. Native Interface(네이티브 인터페이스)
    • Java Native Interface(JNI)를 통해 Java 애플리케이션에서 네이티브 라이브러리를 호출할 수 있습니다.

 

JVM의 특징

  • 플랫폼 독립성: JVM 덕분에 Java 프로그램은 한 번 작성되면 여러 운영 체제에서 실행될 수 있습니다.
  • 자동 메모리 관리: Garbage Collection을 통해 메모리 관리가 자동으로 이루어집니다.
  • 보안성: JVM은 바이트코드를 실행하기 전에 검증하고, 실행 시에도 다양한 보안 검사(예: 바이트코드 검증, 런타임 검사)를 수행합니다.

이와 같이 JVM은 Java 애플리케이션의 실행 환경을 제공하며, 플랫폼 독립적인 실행과 자동 메모리 관리 등 다양한 기능과 장점을 제공합니다.