[Java] Java의 메모리 영역

Jeini·2025년 9월 2일
0

☕️  Java

목록 보기
58/70
post-thumbnail

자바(Java)의 메모리 영역은 프로그램이 실행될 때 JVM(Java Virtual Machine)이 메모리를 어떻게 나눠서 쓰는지에 대한 개념이다.

자바는 JVM 위에서 동작하기 때문에, JVM이 운영체제로부터 메모리를 할당받아 다시 세부적으로 나눠서 관리한다. 크게 나누면 5가지 주요 영역이 있다👇


🧩 Java 메모리 구조

1. 메서드 영역 (Method Area, 클래스 영역)

  • 클래스의 정보(클래스 이름, 메서드, 변수, static 변수, 상수 등)가 저장됨.
  • 프로그램 전체에서 공유됨 (전역 저장소 느낌).
  • 한 번 로딩된 클래스 정보는 여기 저장돼서 어디서든 사용할 수 있다.

👉 ex) static int count = 0; 이런 정적 변수는 여기 들어감.


2. 힙 영역 (Heap Area)

  • new 키워드로 생성된 객체와 배열이 저장되는 공간.
  • GC(Garbage Collector)가 관리하는 곳 (더 이상 참조되지 않는 객체는 제거됨).
  • 모든 스레드가 공유.

👉 ex) new String("hello"), new int[10]


3. 스택 영역 (Stack Area)

  • 메서드가 호출될 때마다 스택 프레임(Stack Frame)이 쌓임.
  • 지역변수, 매개변수, 메서드 호출 정보 등이 저장됨.
  • 메서드가 끝나면 해당 스택 프레임이 사라짐.

👉 ex)

void test() {
    int x = 10; // 스택에 저장됨
}

4. PC 레지스터 (Program Counter Register)

  • 현재 실행 중인 JVM 명령어의 주소(위치)를 저장.
  • 스레드마다 하나씩 존재 (멀티스레드 지원용).
  • CPU의 Program Counter랑 비슷한 개념.

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

  • C/C++ 같은 네이티브 코드 실행 시 사용하는 스택.
  • JNI(Java Native Interface) 호출 시 사용됨.
  • 일반적인 자바 코드에서는 잘 안 보이지만 내부적으로 중요함.

📝 정리

  • 메서드 영역 → 클래스/정적 변수/상수 저장
  • 힙 영역 → 객체/배열 저장 (GC 관리)
  • 스택 영역 → 지역변수/매개변수/메서드 호출 정보
  • PC 레지스터 → 현재 실행 중인 명령어 위치
  • 네이티브 메서드 스택 → C/C++ 네이티브 코드 실행용

🚀 Java 프로그램 실행 시 메모리 로딩 순서

자바 프로그램을 실행하면 JVM이 아래 순서대로 메모리를 세팅한다 👇

1. 클래스 로딩 (Class Loader 단계)

  • .class 파일을 읽어서 메서드 영역(Method Area, Java 8 이후는 Metaspace) 에 클래스 정보를 적재

👉 클래스 이름, 메서드, static 변수, 상수 등이 로딩됨

2. 메서드 영역(Method Area)

  • static 변수와 static 메서드가 먼저 준비됨

👉 아직 객체를 만들지 않아도 클래스명.변수명 으로 접근 가능

3. 스택(Stack) 생성

  • main() 메서드 호출 시, main 스레드의 스택 프레임이 생김
  • 지역변수/매개변수 등이 여기에 저장됨

4. 힙(Heap) 할당

  • new 키워드로 객체 생성 시, 힙 영역에 메모리가 할당됨
  • 참조 변수는 스택에 저장, 객체 자체는 힙에 저장

5. PC 레지스터 & 네이티브 메서드 스택

  • 스레드 실행 위치 관리 (PC Register)
  • 네이티브 코드 실행 시 C/C++용 스택 활용

🧩 예시 코드로 메모리 흐름 보기

class Counter {
    static int count = 0;  // static 변수
    int id;                // 인스턴스 변수

    Counter(int id) {
        this.id = id;
        count++;
    }
}

public class Main {
    public static void main(String[] args) {
        Counter c1 = new Counter(1);
        Counter c2 = new Counter(2);
        System.out.println(Counter.count);
    }
}

✏️ 실행 과정

  1. Counter.class 로딩 → 메서드 영역(Method Area)에 count 변수 준비됨 (0으로 초기화).

  2. main() 실행 → 스택에 argsmain() 스택 프레임 생성.

  3. new Counter(1) → 힙에 객체 c1 생성, id=1.

  • 스택에는 참조변수 c1이 저장됨.
  • count++ 실행 → 메서드 영역의 count 값이 1이 됨.
  1. new Counter(2) → 힙에 또 다른 객체 c2 생성, id=2.
  • count++ 실행 → count=2.
  • System.out.println(Counter.count) → 2 출력.

👉 즉, static은 "클래스 차원에서 미리 준비" / 인스턴스는 "객체 만들 때 준비" 라고 이해하면 된다!

profile
Fill in my own colorful colors🎨

0개의 댓글