> For the complete documentation index, see [llms.txt](https://byulseop-til.gitbook.io/sinheeseop_til/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://byulseop-til.gitbook.io/sinheeseop_til/java/101/jvm_memory_and_static.md).

# JVMMemoryAndStatic

### 1. JVM

자바 메모리 구조를 이해하기 전에, 먼저 **JVM**(Java Virtual Machine)에 대해 간단히 살펴보겠습니다.

#### 1.1 JVM이란?

* **Java Virtual Machine**의 약자. 자바 소스 코드를 컴파일해서 만들어진 **바이트코드(.class)** 를 OS에 종속되지 않고 실행해주는 **가상 머신**입니다.
  * 가능한 이유 [OS 마다 기계 해석이 다른 이유](/sinheeseop_til/java/101/why_different_machine_interpretation_by_os.md) 참고
* JVM만 설치되어 있으면, 어느 운영체제에서든 같은 `.class` 파일을 실행할 수 있는 것이 자바의 큰 장점입니다.

#### 1.2 JVM 실행 순서

1. **소스 컴파일**\
   `.java` → 자바 컴파일러 → `.class`(바이트 코드)
2. **클래스 로더(ClassLoader)**\
   `.class` 파일을 읽어서 **JVM 내로 로딩**, 필요한 클래스를 동적으로 가져옴.
3. **JVM 런타임 영역에 적재**\
   로딩된 클래스가 메모리(Method Area 등)에 올라오고, 프로그램이 실행됩니다.

#### 1.3 JVM의 Run Time Data Area

자바 메모리 영역을 설명할 때는 보통 다음 5가지 구성을 말합니다:

* **Heap Area**
* **Static/Method Area**
* **Stack Area**
* **PC Register**
* **Native Method Stacks**

아래 이미지는 **메인 메서드**가 호출될 때 JVM이 어떻게 구동되는지를 간단히 보여줍니다.

![JVM 구동방식 (메인메서드 호출)](https://3402558153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrRGcHUhpJF1VkrNF6Lbb%2Fuploads%2Fgit-blob-6708702e74669053c1fa9d8365a661c98fdbdc6f%2F03_1.png?alt=media)

1. 클래스 로더가 `.class` 파일을 로드
2. 정적 영역(Static or Method)에 클래스 정보 배치
3. 힙/스택 등 런타임 영역에서 코드가 실행
4. `.class` 내부 정보를 활용해 프로그램이 동작

### 2. 자바의 메모리 영역이란?

자바 애플리케이션이 실행되면, **JVM**은 OS로부터 메모리를 할당받아 여러 개의 영역으로 나누어 사용합니다.\
이 메모리 공간을 **Runtime Data Area**라 부르며, 보통 **Method(Static) 영역, Stack 영역, Heap 영역**이 핵심입니다.

![런타임 데이터 영역(간략)](https://3402558153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrRGcHUhpJF1VkrNF6Lbb%2Fuploads%2Fgit-blob-4c415992d2f0c70f2275a84c3a8fcbd1c14ca28f%2F03_2.png?alt=media)

* **Method(Static) 영역**
* **Stack 영역**
* **Heap 영역**
* **PC Register, Native Method Stacks** (자세한 설명은 아래 참조)

메모리를 효율적으로 구성해야 성능이 좋아집니다. 잘못 구성하거나 지나친 재귀 호출 등으로 `StackOverflowError`가 발생할 수도 있으므로 주의가 필요합니다.

### 3. 자바 변수의 종류

메모리 영역을 살펴보려면, 먼저 **자바에서 변수를 어떻게 분류**하는지 알아야 합니다.

![자바 변수의 종류](https://3402558153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrRGcHUhpJF1VkrNF6Lbb%2Fuploads%2Fgit-blob-4c415992d2f0c70f2275a84c3a8fcbd1c14ca28f%2F03_2.png?alt=media)

1. **클래스 변수** (`static` 변수)
   * 클래스 레벨에서 선언, 모든 객체가 공유 가능.
2. **인스턴스 변수** (멤버 변수)
   * 객체를 생성(`new`)할 때 만들어지며, 각 객체마다 다른 값을 가짐.
3. **매개변수**
   * 메서드 호출 시 전달하는 값을 저장, 메서드가 종료되면 소멸.
4. **지역 변수**
   * 메서드 블록 `{ ... }` 안에서 선언 후, 블록이 끝나면 사라짐.

#### 각 변수의 생성 시점

* **클래스 변수(`static`)** → 클래스 로딩 시
* **인스턴스 변수** → 객체(`new`) 생성 시
* **지역 변수, 매개변수** → 메서드(또는 블록) 실행 시점에 생성

### 4. 자바 메모리 구조

#### 4.1 자바 메모리 구조 - 비유

![자바 메모리 구조 (비유)](https://3402558153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrRGcHUhpJF1VkrNF6Lbb%2Fuploads%2Fgit-blob-4e86398eec9df33ed8e14359b5e27e1e4234c1ee%2F03_3.png?alt=media)

* **메서드 영역**: 클래스 정보를 보관 (붕어빵 틀에 비유)
* **스택 영역**: 메서드 호출 시마다 쌓이는 영역
* **힙 영역**: `new`로 생성된 객체(붕어빵)가 놓이는 곳

#### 4.2 자바 메모리 구조 - 실제

![자바 메모리 구조 (실제)](https://3402558153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrRGcHUhpJF1VkrNF6Lbb%2Fuploads%2Fgit-blob-574b3f8104572e503d55af8ea0580952a6e52129%2F03_4.png?alt=media)

1. **메서드 영역(Method Area)**
   * 프로그램 실행에 필요한 클래스 정보, 필드/메서드/생성자 코드가 보관.
   * `static` 변수(`static` 영역), 런타임 상수 풀도 이곳에 속함.
2. **스택 영역(Stack Area)**
   * 실행 스택을 형성, 메서드 호출 시마다 스택 프레임이 생성.
   * 지역 변수, 매개변수, 임시 연산 결과 저장.
   * 메서드 종료 시 해당 프레임이 제거.
3. **힙 영역(Heap Area)**
   * 객체(인스턴스) 및 배열이 생성되는 영역, GC(가비지 컬렉션)가 참조되지 않는 객체를 회수.
   * 자바 7 이전에는 PermGen 영역이 존재했고, 8 이상에서는 Metaspace 사용 등 구조 변화가 있음.

> **스택**은 쓰레드별로 하나씩 존재, **힙/메서드 영역**은 여러 쓰레드가 공유.

### 5. 메서드 영역 (Method Area)

#### 5.1 클래스 정보

JVM이 클래스 파일을 로드할 때, 해당 클래스의 **메타데이터**(타입, 변수명, 메서드 구조 등)를 메서드 영역에 저장합니다.

#### 5.2 런타임 상수 풀

문자열 리터럴(`"hello"` 등)이나 상수화된 값들이 모여 재사용되는 곳. (자바 7부터 일부는 힙으로 이전)

#### 5.3 static 정보 (정적)

* **정적 변수와 메서드**는 프로그램 시작 시 클래스 로딩과 함께 메모리상에 올라와 종료 때까지(또는 언로드 전) 유지.
* 동적으로 생성되는 인스턴스와 달리, 이미 결정된 시점에 고정(정적)으로 존재한다고 해서 **static**이라 부름.
* 클래스 변수 static 변수, 정적 변수등으로 불리니 헷갈리지 않게 주의

**static 메서드가 멤버 변수를 사용할 수 없는 이유**

* `static` 메서드는 인스턴스 없이 호출 가능.
* 인스턴스 변수는 `new`로 객체를 만들어야 생기므로, `static` 메서드에서는 직접 접근 불가.
* 단, 내부에서 객체를 새로 생성하거나 매개변수로 참조를 받으면 인스턴스 변수를 쓸 수 있음.

### 6. 스택 영역(Stack)

**메서드 실행 시** 사용되는 메모리.

1. 메서드 호출 → 스택 프레임 생성 → 지역 변수, 매개변수 할당.
2. 메서드가 종료되면 해당 스택 프레임 소멸.
3. 재귀나 무한 호출 등으로 스택이 꽉 차면 `StackOverflowError`.

### 7. 힙 영역(Heap)

**객체(인스턴스)와 배열**이 생성되는 영역.

![Heap 구조](https://3402558153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrRGcHUhpJF1VkrNF6Lbb%2Fuploads%2Fgit-blob-4648f56cdf0676d5a6f21e1fee62efdb87eb98fe%2F03_5.png?alt=media)

* 가비지 컬렉션이 참조되지 않는 객체를 제거.
* 여러 쓰레드가 공유하므로 동시성 문제 시 동기화가 필요.
* 자바 8 이후 PermGen이 Metaspace로 변경되는 등 내부 구조가 다를 수 있음.

### 8. 힙 vs 스택 메모리 차이점

![힙 vs 스택](https://3402558153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrRGcHUhpJF1VkrNF6Lbb%2Fuploads%2Fgit-blob-c145018dca7ab69d62166decb038d18e0f831b29%2F03_7.png?alt=media)

1. **공유 범위**
   * 스택: 쓰레드마다 독립 (안전)
   * 힙: 모든 쓰레드가 공유 (동기화 고려 필요)
2. **저장 데이터**
   * 스택: 지역 변수, 매개변수, 참조 변수
   * 힙: 인스턴스(객체), 배열 전체
3. **메모리 에러**
   * 스택: `StackOverflowError`
   * 힙: `OutOfMemoryError(Heap Space)`

### 9. 정리

* 자바 프로그램 시작 시, JVM은 **클래스 정보/메서드/생성자 코드**를 **메서드 영역**에 로드.
* 필요 시, `new`로 **힙에 객체**를 생성.
* 메서드가 호출될 때마다 **스택 프레임**이 생성되어 지역 변수/매개변수를 처리, 종료 시 소멸.
* `static` 변수와 메서드는 클래스 로딩 시 메서드 영역에 자리 잡고, 프로그램 끝날 때까지 유지 가능.

#### 결론

* \*\*클래스 변수(`static`)\*\*는 클래스 로딩 시점,
* **인스턴스 변수**는 `new`로 객체 생성 시점,
* **지역 변수**는 메서드 실행 시점에 각각 생성됨.
* 메모리 구조를 정확히 이해하면 **성능 최적화**, **오류(스택 오버플로우, 메모리 부족) 대처**, **객체 지향 설계** 등에 크게 도움이 된다.
