logo

JVM 작동 방식 - JVM 아키텍처

JVM(Java Virtual Machine)은 Java 프로그램을 수정 없이 모든 플랫폼에서 실행할 수 있도록 하는 JRE(Java Runtime Environment)의 핵심 구성 요소입니다. JVM은 Java 바이트코드와 Java의 유명한 WORA(Write Once Run Anywhere) 기능을 제공하는 기본 하드웨어 간의 인터프리터 역할을 합니다.

  • Java 소스(.java) -> javac로 컴파일됨 -> 바이트코드(.class)
  • JVM은 바이트코드를 로드하고 링크를 확인한 후 실행합니다.
  • 실행에는 바이트코드를 해석하거나 JIT(Just-In-Time) 컴파일을 사용하여 성능을 위해 핫 코드를 기본 기계어 코드로 변환하는 작업이 포함될 수 있습니다.
  • 가비지 수집은 사용하지 않는 객체에서 메모리를 회수하기 위해 백그라운드에서 실행됩니다.

JVM의 아키텍처

아래 이미지는 JVM의 아키텍처와 주요 구성 요소를 보여줍니다.

JVM' title=

JVM 아키텍처의 구성 요소

이제 JVM의 각 구성 요소에 대해 자세히 설명하겠습니다.



1. 클래스 로더 서브시스템

크게 3가지 활동을 담당합니다. 

클래스 로더_하위 시스템' loading='lazy' title=

1. 로딩

  • .class 파일을 읽고 메서드 영역에 클래스 메타데이터를 저장합니다.
  • 로드된 클래스를 나타내는 힙에 Class 개체를 만듭니다.
Java
class GFG{    static{    System.out.println('GFG class is loaded by the JVM!');  }  public void display(){    System.out.println('Method of GFG class is executed.');  } } public class Test{  public static void main(String[] args) throws Exception{    System.out.println('Main method started.');  // Loading the class explicitly using Class.forName()  Class.forName('GFG');  System.out.println('Class loaded successfully.');  // Creating object to execute method  GFG obj = new GFG();  obj.display();  } } 

산출
Main method started. GFG class is loaded by the JVM! Class loaded successfully. Method of GFG class is executed. 

메모: 로드된 모든 항목에 대해 .수업 파일만 하나 클래스의 객체가 생성됩니다.

2. 연결: 실행을 위해 로드된 클래스를 준비하는 일을 담당합니다. 여기에는 세 가지 단계가 포함됩니다.

  • 확인: 바이트코드가 JVM 규칙을 따르고 실행하기에 안전한지 확인합니다.
  • 준비: 정적 변수에 메모리를 할당하고 기본값을 할당합니다.
  • 해결: 기호 참조를 메모리의 직접 참조로 변환합니다.

3. 초기화

  • 정적 변수에 실제 값을 할당합니다.
  • 클래스에 정의된 정적 블록을 실행합니다.

클래스 로더 유형

  • 부트스트랩 클래스 로더: 핵심 Java 클래스(JAVA_HOME/lib)를 로드합니다.
  • 확장 클래스 로더: 확장 디렉토리(JAVA_HOME/jre/lib/ext)에서 클래스를 로드합니다.
  • 시스템/애플리케이션 클래스 로더: 애플리케이션 클래스 경로에서 클래스를 로드합니다.
Java
// Java code to demonstrate Class Loader subsystem public class Geeks  {  public static void main(String[] args)  {  // String class is loaded by bootstrap loader and  // bootstrap loader is not Java object hence null  System.out.println(String.class.getClassLoader());  // Test class is loaded by Application loader  System.out.println(Geeks.class.getClassLoader());  } } 

산출
null jdk.internal.loader.ClassLoaders$AppClassLoader@8bcc55f 

2. JVM 메모리 영역

  • 방법 영역: 클래스 이름 상위 클래스 메서드 변수 및 정적 데이터와 같은 클래스 수준 정보를 저장합니다. JVM 전체에서 공유됩니다.
  • 힙 영역: 모든 객체를 저장합니다. JVM 전체에서 공유됩니다.
  • 스택 영역: 각 스레드에는 자체 런타임 스택이 있습니다. 메소드 호출 지역 변수를 스택 프레임에 저장합니다. 스레드가 끝나면 삭제됩니다.
  • PC 레지스터: 각 스레드에 대해 현재 실행 중인 명령어의 주소를 보유합니다.
  • 네이티브 메서드 스택: 각 스레드에는 기본 메서드 실행을 위한 별도의 스택이 있습니다.

3. 실행 엔진 

실행 엔진은 .class(바이트코드)를 실행합니다. 바이트코드를 한 줄씩 읽어 각종 메모리 영역에 존재하는 데이터와 정보를 이용하여 명령어를 실행한다. 이는 세 부분으로 분류될 수 있습니다:

  • 통역사: 바이트코드를 한 줄씩 해석한 다음 실행합니다. 여기서 단점은 하나의 메서드를 여러 번 호출할 때마다 해석이 필요하다는 점입니다.
  • JIT(Just-In-Time 컴파일러): 통역사의 효율성을 높이기 위해 사용됩니다. 전체 바이트코드를 컴파일하고 네이티브 코드로 변경하므로 인터프리터가 반복적인 메서드 호출을 볼 때마다 JIT는 해당 부분에 대한 직접 네이티브 코드를 제공하므로 재해석이 필요하지 않으므로 효율성이 향상됩니다.
  • 가비지 컬렉터: 참조되지 않은 객체를 파괴합니다. 가비지 수집기에 대한 자세한 내용은 다음을 참조하세요. 가비지 컬렉터 .

4. 자바 네이티브 인터페이스(JNI)

Native Method Libraries와 상호작용하고, 실행에 필요한 네이티브 라이브러리(C C++)를 제공하는 인터페이스입니다. 이를 통해 JVM은 C/C++ 라이브러리를 호출하고 하드웨어에 특정한 C/C++ 라이브러리에 의해 호출될 수 있습니다.

5. 네이티브 메소드 라이브러리

네이티브 메서드를 실행하는 데 필요한 네이티브 라이브러리 모음입니다. 여기에는 C 및 C++와 같은 언어로 작성된 라이브러리가 포함됩니다.