본문 바로가기

프로그래밍 기초

JVM 기초 개념 요약 정리

※ 틀린 부분이 있을 수 있으며, 피드백은 언제나 환영합니다.

서술형(답이 비어 있는 버전) 링크

https://docs.google.com/document/d/1F0h8rVfLXod2LdtfZset4mREay99TzdWMWtUqyBBkLg/edit?usp=sharing


JVM 아키텍처 구성 요소

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

ㄴ 스레드를 통한 영역 구분:

스레드 간 공유되는 영역: 메소드 영역, 힙 영역
스레드간 독립적인 영역: 스택 영역, PC(Program Counter) 레지스터, 네이티브 메소드 스택

ㄴ 각 영역에 저장되는 것:

메소드 영역: 타입 정보, 필드 정보, 메소드 정보, 런타임 상수 풀, 클래스 변수.
힙 영역: 런타임 동안 생성된 객체.
스택 영역: 지역 변수, 중간 계산 결과, 메소드 호출 정보.
PC 레지스터: 현재 실행된 JVM 명령의 주소.
네이티브 메소드 스택: Java 이외의 언어로 작성된 네이티브 메소드의 실행에 필요한 정보.

ㄴ 힙에서의 Young Gen과 Old Gen을 나누는 기준(약한 세대 가설, Weak Generational Hypothesis):

    ㅡ 대부분의 객체는 젊은 나이에 죽는다.

    ㅡ 오랫 동안 살아남는 객체는 장기간 동안 계속해서 살아남는다.

 힙에서의 Young Gen과 Old Gen이 다루는 객체:

    ㅡ Young Gen: 모든 새로운 객체.

    ㅡ Old Gen: Young Gen에서 GC의 몇 번의 순회에서 살아남은 수명이 긴 객체.

 

인터프리터(Interpreter)

ㄴ 역할: Java 바이너리 파일에 있는 바이트 코드를 명령어 단위로 읽으면서 JVM이 이해할 수 있는 기계어로 해석 및 실행한다.

ㄴ 버전별 변천사:

    ㅡ Java 1.0: 순수한 실행자로서의 인터프리터

    ㅡ Java 1.2: 인터프리터에 프로파일링 기능 도입, PermGen에서 메모리 관리

    ㅡ Java 1.7: 계층화된 컴파일 도입, 명령 집합 확장(동적 링킹)

    ㅡ Java 1.8: PermGen이 Metaspace로 대체됨

 

클래스 로더(Class Loader)

ㄴ 역할: 컴파일된 클래스 중에서 JVM의 런타임 데이터 영역에 필요한 클래스를 런타임에 메모리에 불러온다.

ㄴ 종류:

부트스트랩 클래스 로더(Bootstrap Class Loader): Java 클래스를 로드할 수 있는 Java 자체의 클래스 로더와 최소한의 Java 클래스를 로드한다.
플랫폼 클래스 로더(Platform Class Loader): Java 플랫폼에 속하는 모든 클래스를 로드한다.
애플리케이션 클래스 로더(Application Class Loader): 유저가 정의한 클래스에 대한 디폴트 클래스 로더이다.

 

ㄴ 동작 과정: 

로딩: .class 파일에 들어 있는 바이너리 스트림을 파싱하여 얻어낸 바이너리 데이터를 메소드 영역에 저장, 해당 클래스 타입의 Class 객체를 힙에 저장.
=>
링킹:
ㄴ 검증: 로딩 과정을 통해 저장된 바이너리 데이터가 형식적인 오류가 없음을 보장.
ㄴ 준비: static 필드에 메모리 할당, 가상 메소드 테이블 생성.
ㄴ 분석: 메소드 영역에 런타임 상수 풀 형태로 로드되었던 심볼릭 레퍼런스가 JVM에 의해 분석되고 메모리에 로드되어 주소를 갖게 됨.
=>
초기화: static 필드에 값 할당, 클래스에 static 블록이 있다면 이를 실행.

JVM 아키텍처 구현 방식

네이티브 메모리(Native Memory)

ㄴ 의미: JVM 프로세스 스스로에 의해 기저 OS로부터 할당받는 메모리 중 관리되는 힙 바깥에 위치한 메모리.

ㄴ 포함되는 것: Metaspace, 스레드 스택, JIT로 컴파일된 코드, GC 및 JVM 내부 구조.


JVM 실행 과정

1. OS로부터 JVM이 하나의 프로세스로서 실행되며, JVM이 실행되는 데 필요한 메모리를 OS로부터 할당받는다.
2. 부트스트랩 클래스 로더는 JVM가 실행되기 위해 필요한 최소한의 클래스들을 로딩, 검증, 준비, 분석 후 초기화를 거쳐 로딩한다.
3. 인터프리터가 바이트 코드를 명령어 단위로 번역하면서:

메소드 영역: 클래스에 관한 정보는 메소드 영역으로부터 참조한다.
힙 영역: new 연산자를 만나면 힙에 객체를 생성한다.
PC 레지스터: 다음에 실행할 명령어가 위치한 메모리 주소를 PC 레지스터에 기록한다.
스택 영역: 메소드가 호출되면 해당 스레드의 스택에 프레임을 푸시한다.
JIT 컴파일: JIT 컴파일러가 핫 메소드를 감지하고 이를 네이티브 머신 코드로 컴파일하여 캐싱한다.

4. JVM이 메인 스레드를 생성하고 main() 메소드를 호출한다.
5. 힙 메모리가 부족하거나 기타 필요 시 가비지를 수집한다.


관련 기능 & 기술

계층화된 컴파일(Tiered Compilation)

ㄴ 의미: 프로그램의 시작 속도와 장기적인 실행 성능을 모두 최적화하기 위해 여러 단계의 컴파일러를 조합하여 사용하는 기법.

 

동적 클래스 로딩(Dynamic Class Loading)

ㄴ 의미: JVM에서 실행에 필요한 모든 클래스 파일을 한 번에 메모리에 올리지 않고, 필요한 시점에 동적으로 올리는 기술.

ㄴ 이점: 가능한 적은 클래스 파일을 메모리에 올릴 수 있으므로 더욱 효율적이다.

 

클래스 데이터 공유(Class Data Sharing)

ㄴ 의미: 다수의 JVM 인스턴스 간에 클래스 메타데이터와 같은 읽기 전용 데이터를 공유하는 것을 허용하는 JVM의 특징.

ㄴ 이점: 스타트업에 메모리에 로드될 필요가 있는 데이터의 양을 줄임으로써 Java App의 스타트업 시간을 개선한다.

'프로그래밍 기초' 카테고리의 다른 글

Java 기초 개념 요약 정리(2)  (0) 2026.02.05
아키텍처 기초 개념 요약 정리  (0) 2025.12.09
Java 기초 개념 요약 정리(1)  (0) 2025.12.08