Post

JVM(자바 가상 머신)의 구성 요소들

JVM의 구성 요소와 각각의 기능들을 정리

JVM(자바 가상 머신)의 구성 요소들

JVM의 구조


JVM_Structure

JVM의 구조1

  • Class Loader(클래스 로더)

  • Execution Engine(실행 엔진)
    • Interpreter(인터프리터)
    • Just-In-Time(JIT 컴파일러)
    • Garbage Collector(가비지 콜렉터)
  • Runtime Data Area(런타임 데이터 영역)
    • Method Area(메소드 영역)
    • Runtime Data Area(힙 영역)
    • PC Register(PC 레지스터)
    • JVM Stack(스택 영역)
    • Native Method Stack(네이티브 메소드 스택 영역)
  • JNI - Native Method Interface(네이티브 메소드 인터페이스)
  • Native Method Library(네이티브 메소드 라이브러리)


Class Loader (클래스 로더)


  • 클래스 로더는 클래스가 참조될 때 JVM의 메모리에 클래스(.class)를 로드하는 작업을 담당함. 필요한 클래스 파일을 검색하여 메모리에 로드하여 각 클래스가 한 번만 로드되도록 한다.

  • Runtime 시 동적으로 로드. .jar 파일 내 저장 된 클래스들을 JVM 위에 탑재하고, 사용하지 않는 클래스들은 메모리에서 삭제함.

  • 클래스 로더는 로드된 클래스의 무결성 확인 및 클래스 간의 종속성 해결과 같은 중요한 작업도 수행함.


Execution Engine (실행 엔진)


  • 클래스 로더가 JVM내의 Runtime Data Area에 바이트코드(.class)를 배치시키면 실행엔진이 해석. 즉, JVM 만이 바이트코드를 이해할 수 있기 떄문에 실행엔진이 기계가 이해할 수 있게 변환함.

  • Java는 2가지의 방식을 혼합하여 바이트코드를 해석하는데 인터프리터JIT 컴파일러다. 인터프리터는 한 줄씩 해석하기에 방식이 속도가 느리기에 이 단점을 보완하기 위해 새로운 해석 방식인 JIT 컴파일러이다.

  • Interpreter(인터프리터)
    • JVM은 기본적으로 인터프리터 방식으로 동작한다. 다만 같은 메소드 라도 여러번 호출이 된다면 매번 해석하고 수행해야 되서 전체적인 속도는 느리다.
  • Just-In-Time Compiler(JIT 컴파일러)
    • 바이트 코드 전체를 컴파일하여 Native Code로 변경하고 이후에는 해당 메서드를 더 이상 인터프리팅 하지 않고 캐싱해 두었다가 Native Code로 직접 실행하는 방식이다.
    • 하지만 바이트 코드를 Native Code로 변환하는 데에도 비용이 소요되므로, JVM은 모든 코드를 JIT 컴파일러 방식으로 실행하지 않고 인터프리터 방식을 사용하다 일정 기준이 넘어가면 JIT 컴파일 방식으로 명령어를 실행하는 식으로 진행한다.

Native Code : C언어나, C++, 어셈블리어로 구성된 코드를 의미


Garbage Collector (G.C, 가비지 컬렉터)


  • JVM이 Heap Area를 감시하다가 더 이상 사용되지 않는 객체(== 참조되지 않는 객체)를 자동으로 메모리에서 해제하는 기능.

C나 C++의 free()delete를 직접 호출하지 않아도, 자바는 JVM의 가비지 컬렉터(GC)가 알아서 필요 없는 객체를 정리함


G.C 동작 과정


  1. 객체 생성 –> Heap Area에 저장됨

  2. 변수 참조가 끊김 –> 객체를 가리키는 Reference가 없어짐

  3. GC 탐색(Reachability Analysis)
    • 루트(root) 객체에서 접근할 수 없는 객체를 Garbage로 판단
  4. Mark and Sweep (표시하고 쓸기)
    • Mark 단계 : 살아있는 객체 표시
    • Sweep 단계 : 표시되지 않은 객체(가비지) 제거
    • Compact 단계(선택적) : 남은 객체들을 메모리 앞쪽으로 모아 단편화 해소


Runtime Data Area (런타임 데이터 영역)


Runtime_Data_Area1

Runtime Data Area 12

  • JVM이 자바 프로그램을 실행할 때 사용하는 메모리 영역 구조 이다. 각 영역은 서로 다른 목적(클래스 정보 저장, 스택 관리, 힙 객체 저장 등)을 가지고 있음.

  • 사진과 같이 Method Area, Heap Area는 모든 쓰레드(Thread)가 공유하는 영역이고, 나머지 Stack Area, PC Register, Native Method Stack 은 각 쓰레드 마다 생성되는 개별 영역이다.

영역특징 / 역할생성 시점스레드 공유 여부
Method Area (메서드 영역)클래스의 구조 정보(메서드, 필드, static 변수, 상수 등)를 저장JVM 시작 시공유
Heap Area (힙 영역)new로 생성된 객체와 배열 저장JVM 시작 시공유
Stack Area (스택 영역)각 스레드의 메서드 호출 정보 저장 (지역 변수, 매개변수, return 값 등)스레드 생성 시개별
PC Register (프로그램 카운터)현재 실행 중인 JVM 명령어 주소를 저장스레드 생성 시개별
Native Method Stack (네이티브 메서드 스택)C/C++ 등 네이티브 코드 실행용 스택스레드 생성 시개별

Runtime_Data_Area2

Runtime Data Area 23


Method Area (메서드 영역)


  • 클래스 로더가 읽어온 클래스, 메서드, 필드, static 변수, 상수 등의 정보를 저장

  • 프로그램 전체에서 공유되는 영역으로, 모든 스레드가 접근할 수 있음

  • JDK 8 이후에는 Metaspace로 대체되어, 네이티브 메모리 영역에 저장


Heap Area (힙 영역)


  • new 키워드로 생성된 객체와 배열이 저장되는 영역

  • GC(Garbage Collector)가 동작하는 유일한 영역

  • 모든 스레드가 공유하며, 가장 큰 메모리 공간을 차지함


Stack Area (스택 영역)


  • 메서드 호출 시 생성되는 스택 프레임(지역 변수, 매개변수, 리턴 값 등)을 저장

  • 스레드마다 독립적으로 생성되어 다른 스레드와 공유되지 않음

  • 메서드가 종료되면 해당 스택 프레임은 자동으로 소멸


PC Register (프로그램 카운터 레지스터)


  • 현재 JVM 명령어의 실행 위치(주소)를 저장

  • 각 스레드마다 존재하며, 멀티스레드 환경에서 실행 흐름을 추적

  • JVM이 어떤 명령을 다음에 실행할지를 결정하는 데 사용


Native Method Stack (네이티브 메서드 스택)


  • C, C++ 등 자바 외부 언어(JNI)로 작성된 메서드 실행 시 사용

  • 각 스레드마다 생성되며, 네이티브 코드 호출 시 스택 프레임 관리를 담당

  • 자바 스택과 유사하지만, JVM 외부 코드 실행용이라는 점이 다름


추천 게시물



Reference



  1. 출처 : https://velog.io/@bluegrate/java%EC%9D%98-%EB%8F%99%EC%9E%91%EA%B3%BC%EC%A0%95%EA%B3%BC-JVM%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0 ↩︎

  2. 출처 : https://hongchangsub.com/java3/ ↩︎

  3. 출처 : https://goldenrabbit.co.kr/2021/11/03/%EC%9E%90%EB%B0%94-%EC%BD%94%EB%93%9C%EC%99%80-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%8A%A4%ED%83%9C%ED%8B%B1-%EB%B3%80%EC%88%98-%EB%93%B1%EC%9D%80-%EB%A9%94%EB%AA%A8%EB%A6%AC%EC%9D%98-%EC%96%B4%EB%94%94/ ↩︎

This post is licensed under CC BY 4.0 by the author.