Notice
Recent Posts
Recent Comments
Link
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

Fear is a habit. I'm not afraid.

JVM의 메모리 구조 본문

basic

JVM의 메모리 구조

sylviaisthebest 2025. 5. 2. 12:30

자바 프로그래밍 수업 중에 메모리 구조에 대한 간단한 설명을 들었다.
기본적인 개념이지만 복습 차원에서 찾아보게 되었고, 한 아티클이 정리가 잘 되어 있어 내용을 정리해보았다.
추가적으로 다소 모호하게 느껴졌던 표현들은 정확히 무엇을 의미하는지 찾아보면서 보완했다.

 


 

JVM은 몇 가지 유형의 메모리 영역을 할당할까?

 

JVM(Java Virtual Machine)은 추상 머신, 즉 Java 바이트코드를 가져와서 바이트 코드를 한 줄씩 기계가 이해할 수 있는 코드로 변환하는 프로그램/소프트웨어이다. JVM은 Java 애플리케이션을 실행하는 런타임 엔진 역할을 한다. JVM은 Java 코드에 존재하는 주요 메서드를 호출하는 엔진이다. JVM은 JRE(Java Runtime Environment)의 일부이다.

JVM이 수행하는 작업

  • 코드 로드(Loading of codes): JVM은 Java 바이트코드가 포함된 클래스 파일(.class)을 읽어 Method Area에 로드한다. 즉, 필요한 파일을 찾아서 실행할 수 있도록 준비한다. 이 때 로드되는 정보는 다음과 같다.
    • 클래스 이름, 부모 클래스 정보
    • 필드, 메서드 정보
    • 메서드의 바이트코드
    • 정적 변수
    • 상수 풀 (문자열 리터럴 등)
  • 코드 확인(Verification of code): JVM은 로드한 바이트코드가 정확하고 안전한지 확인하기 위해 이를 검사함.
  • 코드 실행(Executing the code): JVM은 확인된 바이트코드를 컴퓨터가 이해할 수 있는 기계어 코드로 변환하여 실행함.
  • 런타임 환경 제공(Providing a Runtime Environment): JVM은 시스템 리소스, 메모리, 가비지 컬렉션을 관리하는 데 도움이 되는 런타임 환경을 제공함.

 

ClassLoader 서브시스템

클래스로더는 클래스 파일을 로드하는 JVM의 하위 시스템으로, 주로 세 가지 작업을 수행한다.

  • 로딩(Loading) : 클래스 파일을 디스크에서 찾아 JVM 메모리에 로드.
  • 연결(Linking) : 클래스 파일을 결합하고 종속성을 해결.
    • 검증(Verification) : 클래스 형식이 유효한지 확인
    • 준비(Preparation) : static 변수 공간 할당 및 기본값 설정
    • 해결(Resolution) : 상수 풀에서 심볼릭 참조를 실제 메모리 참조로 변환
  • 초기화(Initialization) : static 변수를 초기화하고 static 블록을 실행.

코드 예시

public class MyClass {
    static int count = 10;

    static {
        System.out.println("Execute the class initialization block!");
    }
}
  • Myclass.class 파일이 로드될 때 클래스 정보가 메서드 영역에 올라감.
  • 이후 초기화 단계에서 count = 10 이 적용되고, static 블록이 실행됨.

 

JVM이 할당하는 메모리 영역 유형

JVM은 작업을 수행하기 위해 5개의 서로 다른 영역에 메모리를 할당한다.

  1. Method(Class) Area
  2. Heap
  3. Stack
  4. Program Counter Register (PC Register)
  5. Native Method Stack

JVM Architecture diagram

 

1. Method(Class) Area

Method(Class) Area, 즉 메서드 영역은 JVM의 메모리 블록으로 클래스에 대한 중요한 정보를 저장한다.

  • 클래스 코드(Class Code) : 클래스 자체를 정의하는 바이트코드.
  • 변수 코드(Variable Code) : 여기에는 클래스와 관련된 정적 변수와 런타임 상수가 포함된다.
  • 메서드 코드(Method Code) : 생성자를 포함하여 클래스에 정의된 모든 메서드의 바이트코드.

클래스 영역은 런타임 상수 풀, 필드 및 메서드 데이터, 메서드 코드 등 모든 클래스의 클래스 수준 데이터를 메서드 영역 자체에 저장하여 JVM이 Java 프로그램을 효과적으로 실행할 수 있도록 한다.

 

코드 예시

public class Dog {
    static int count = 0;

    String name;
    void bark() {
        System.out.println("Bark");
    }
}
  • Dog 클래스가 처음으로 로드될 때, Dog.class의 구조와 bark() 메서드 바이트코드, static int count는 메서드 영역에 저장된다.

 

2. Heap

Heap은 JVM에서 모든 객체가 생성되고 저장되는 메모리 블록이다. 힙 영역은 다음과 같은 용도로 메모리를 할당하는 데 사용된다.

  • 객체(Objects) : 프로그램 실행 중에 생성되는 클래스의 인스턴스.
  • 클래스 인터페이스(Class Interfaces) : 클래스 인터페이스에 대한 메모리도 여기에 할당.
  • 배열(Arrays) : 배열은 Java에서 객체로 간주되므로 메모리도 힙에 할당.

참고: 정적 메서드와 변수는 이전에는 클래스 영역(Java 8 이전)에 저장되었으나, 현재 Java 버전에서는 정적 변수와 메서드가 힙 메모리에 저장된다.

 

힙 영역은 동적 메모리 할당에 필수적이며, 이를 통해 JVM이 런타임에 객체에 대한 메모리를 할당할 수 있다.

 

코드 예시

Dog myDog = new Dog();
myDog.name = "Happy";
  • new Dog() 로 생성된 객체는 힙에 저장되고, name 필드에 "Happy" 라는 값이 저장된다. 이 객체는 myDog 참조변수를 통해 접근된다.

 

3. Stack

  • Java에서는 각 스레드마다 런타임 스택이라는 자체 스택이 있는데 , 이는 스레드가 시작될 때 생성된다.
    • 프로세스나 코드 또는 스레드를 실행해야 할 때마다 실행 중에 수행되는 작업을 저장하기 위해 런타임 스택이 생성된다. 
  • JVM은 Java 스택에서 두 가지 작업만 직접 수행한다. 즉, 프레임을 Push하고 Pop하는 것이다.
    • 프레임이란 메서드 호출 시 생성되는 메모리 블록으로, 하나의 프레임에는 지역변수, 매개변수, 반환 주소, 예외 핸들링 등과 같은 정보가 담긴다. 프레임을 Push 한다는 것은 메서드가 호출될 때 새로운 프레임을 스택 위에 쌓는 것이며, Pop은 메서드가 종료될 때 프레임을 제거하고 스택에서 꺼내는 것을 뜻한다.
  • 스레드에서 수행되는 모든 메서드 호출은 해당 런타임 스택에 저장된다.
  • 모든 메서드 호출이 완료되면 스택은 비워지고, 그 빈 스택은 스레드를 종료하기 직전에 JVM에 의해 파괴된다.

코드 예시

public class Main {
    public static void main(String[] args) {
        int x = 10;
        Dog d = new Dog();
        greet(x);
    }

    static void greet(int value) {
        System.out.println("Hello " + value);
    }
}
  • x, d, value 와 같은 지역 변수들은 각 메서드 프레임의 스택에 저장이 된다.
  • 메서드 호출 시 push, 종료 시 pop이 된다.

 

4. Program Counter Register (PC Register)

  • 특정 메서드의 작업을 수행하는 각 JVM 스레드에는 해당 스레드와 연관된 프로그램 카운터 레지스터가 있다.
  • 네이티브가 아닌 메서드에는 사용 가능한 JVM 명령어의 주소를 저장하는 PC가 있는 반면, 네이티브 메서드에서는 프로그램 카운터의 값이 정의되지 않는다.
  • PC 레지스터는 특정 플랫폼의 반환 주소나 네이티브 포인터를 저장할 수 있다.

 

5. Native Method Stack

C Stack이라고도 불리는 네이티브 메서드 스택은 자바 언어로 작성되지 않는다. 이 메모리는 각 스레드가 생성될 때 할당되며, 고정 또는 동적일 수 있다.

 

코드 예시

public class Example {
    public native void doSomething();
}
  • doSomething() 메서드는 JVM이 내부적으로 JNI(Java Native Interface를 사용해 C/C++ 코드를 호출한다.
  • 실행 시, 네이티브 메서드 라이브러리(.dll(Windows), .so(Linux) 등) 을 로드해야 한다.

 

 

출처

https://www.geeksforgeeks.org/how-many-types-of-memory-areas-are-allocated-by-jvm/