# 메모리 관리

<figure><img src="https://946524419-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZqOTWctN1y9hEXEl4sKd%2Fuploads%2FosRyUrXECbQP9AKp0Soz%2Fimage.png?alt=media&#x26;token=5ec8d30c-c8db-4999-a657-06d654b20028" alt=""><figcaption><p>JVM Memory Architecture</p></figcaption></figure>

## stack

* 스레드 생성 시 할당된다
* 메서드 실행 관련 정보가 프레임 단위로 저장된다
* 너무 많은 메서드가 호출되어 스택에 쌓이게 되면 흔히 볼 수 있는(?) StackOverFlowError가 발생한다.
* 스택을 생성하거나 동적으로 크기를 확장할 때 메모리가 부족하면 OutOfMemoryError가 발생한다.
* 프레임
  * JVM stack에 생성되는 메서드 관련 정보 저장 단위
  * 메서드가 호출될 때 생성(push)되며 종료되면 소멸(pop)됨
  * 각 프레임에는 런타임에 필요한 메서드 참조를 위해 런타임 상수 풀 참조를 포함
  * 구성 요소
    * Local Variables
      * 매개 변수와 지역 변수를 저장
      * 컴파일 타임에 결정되며  관련 메서드, 클래스 등의 정보와 함께 바이트코드로 제공
      * JVM에 의해 메서드 호출 시 매개 변수(또는 Args)는 지역 변수 배열에 담겨 전달
      * 인스턴스 메서드 호출 시 지역 변수 0은 인스턴스 메서드 객체 참조인 `this`를 전달하는데 사용 하고 1부터 매개변수들이 표현된다
    * Operand Stack
      * 실행 중간 연산 결과 등을 임시로 저장해두는 스택으로 push/pop 명령어에 의해 액세스 가능
      * JVM은 지역 변수, 필드의 값을 오퍼랜드 스택으로 로딩하는 명령을 제공하며 

        다른 명령들을 통해 오퍼랜드 스택에서 값을 가져와 연산, 결과를 다시 저장함
      * 호출할 메서드에 전달할 매개 변수 전달과 결과를 수신할 때도 사용됨
    * Frame Data
      * 연관된 메서드의 심볼릭 레퍼런스와 메서드 반환에 필요한 정보 저장
      * 예외가 발생한 경우 catch 블록 정보를 제공하는 Exception 테이블 참조 포함

## Heap

* JVM 실행 시 생성되어 모든 객체의 인스턴스, 배열 등이 할당되는 영역
* 모든 스레드와 공유해 thread-safe하지 않아 문제가 될 수 있다.
* 힙의 크기는 상황에 따라 유동적이며, 순차적일 필요가 없다.
* 공식적으로 GC가 처리되는 유일한 영역

{% hint style="info" %}
**Stack Memory vs Heap Memory 비교**

* 스택 메모리
  * 메서드 실행/완료에 따라 메모리 크기가 변경된다.
  * 메모리 크기는 OS에 의존적이며 보통은 힙보다 작다.
  * 메모리 할당 속도가 매우빠르다.
  * 메모리 할당과 해제는 메서드 호출에 따라 이뤄진다.
  * 스레드 별로 할당되어 thread-safe 하다.
* 힙 메모리
  * Young Generation, Old Generation 같은 메모리 엑세스 기술이 활용된다.
  * 메모리 크기에 제한이 없어 생성된 모든 객체를 저장한다.
  * GC에 의해 메모리가 관리된다.
  * 메모리를 여러 스레드들이 접근하여 thread-safe하지 않다.
    {% endhint %}

## Method

* JVM 실행 시 생성되어 모든 스레드에게 공유된다
* 클래스 별 구조나 메타 데이터를 저장
  * 초기화에 사용되는 스페셜 메서드(인스턴스 초기화 메서드, 클래스 초기화 메서드, 런타임에 메서드 시그니처가 결정되는 메서드)
  * 런타임 상수 풀, 필드/메서드 데이터
  * 생성자/ 메서드 코드
* 논리적으로는 힙의 일부이다
* 메서드 영역의 크기는 유동적이다.

### 런타임 상수 풀

* 클래스/인터페이스가 로딩되어 생성될 때 Method 영역에 할당되는 자료구조
* 컴파일 시 \`.class\` 파일에 생성되는 일반 상수 풀의 런타임 표현
* 일반 상수 풀의 데이터를 기반으로 생성되며 스태틱 상수, 스태틱 메서드, 심볼릭 레퍼런스(또는 실제 참조) 등을 포함

#### 상수 풀

* Java 바이트코드에 포함되어 있는 모든 상수 값을 저장하는 심볼(룩업) 테이블 
* .java 파일이 Java 컴파일러에 의해 컴파일 되어 Java 바이트코드로 변환될 때 생성
* 클래스명, 필드명, String/Primitive type 리터럴, 심볼릭 레퍼런스 등이 저장됨
* 컴파일 타임 시점에 알 수 있는 정보들이 저장되며, 런타임 시점에는 런타임 상수 풀로 일부 데이터가 이동한다.
* 상수 풀에서 런타임 상수 풀로 가는 경우
  * 심볼릭 레퍼런스나 String.intern 등 런타임에 달라질 수 있는 데이터
  * 컴파일 타임에 확정되어 런타임에 변경되지 않는 데이터(리터럴 값 등)들을 제외한 데이터

## Native Method Stacks

* JNI, 네이티브 라이브러리 사용 시 데이터가 저장되는 영역

## PC Register

* 스레드 생성 시 생성/할당되며 현재 실행 중인 명령의 주소를 저장하는 영역
* 레지스터는 프로세서 내에서 자료를 보관하는 빠른 기억 장치
* 저장되는 명령의 주소는 Java 바이트 스트림(바이트코드) 안에 오프셋을 의미
* 자바 메서드의 경우에만 실행 명령의 주소 저장한다. (opcode)
* JNI 메서드는 저장되지 않는다.
