JVM 메모리 구조
런타임 데이터 영역이란 JVM으로 돌아가는 애플리케이션을 실행할 때 필요한 데이터가 올라가는 영역이다.
크게 Method, Heap, Stack영역과 PC Register, Native Method Stack이 있는데 이번에는 앞에 3개의 영역만 다뤄 보려 한다.
메서드 영역 (Method Area)
메서드 영역은 Class Area, Static Area 라고도 불리며 바이트 코드가 클래스 로더를 거쳐 넘어온 정보를 저장하는 공간이다.
이렇게 넘어온 정보들은 프로그램이 종료될 때까지 유효하다.
저장되는 정보
- Static Field의 이름, 데이터 타입, 접근 제한자 정보
- Method의 이름, return 타입, 메서드의 매개변수, 접근 제한자 정보
- Type(class, enum, intepace)정보와 부모의 정보
상수 풀 (Runtime Constant Pool)
메서드 영역에 위치한 영역으로 다음과 같은 조건을 만족하면 상수풀에 저장될 수 있다.
- 할당된 데이터가 숫자 리터럴(primitive literal) 이거나 문자열 리터럴(String literal) 혹은 이 둘이 결합된 값일 것.
- ex) 1, "A", 1+"A"
- static final로 선언되어야할 것.
- ex) static final int num = 1;
이 두 조건이 만족하면 constant pool에 저장이 된다.
String은 String pool에 저장되는 거 아닌가?
결론부터 말하면 맞다.
그럼 상수 풀과 이름이 같기 상수 풀이 메서드 영역에 독립적으로 존재하는 것처럼 문자열 풀도 상수 풀에 독립적으로 존재할 거 같은 느낌이 든다.
하지만 String pool은 힙 영역에 존재한다.
그렇다면 위에 설명한 static final String은 어떻게 상수 풀에 있는가 설명하면 상수 풀에 있는 문자열 정보는 사실 리터럴이 아니라 레퍼런스(Reference)가 저장이 된다.
그림으로 보자면 다음과 같다
힙 영역 (Heap Area)
힙 영역에는 new 연산자로 생성되는 인스턴스(Class, 배열 등)가 담기는 곳이다.
이곳에 담기는 정보들은 null로 선언하거나 GC(Garvage Collction)에 의해 해제될 때까지 유효하다.
GC란?
Java에서 메모리 누수가 없이 안전하게 객체를 해제하기 위해 JVM이 자동으로 수행하는 메모리 관리 기법이다.
GC에서는 크게 2가지 영역이 있다
Young 영역(Young Generation)
- Eden
- new연산자를 통해 새로 생성된 인스턴스가 위치
- eden에 할당 공간이 부족하면 servivor로 보내진다
- servivor 0 / servivor1
- 최소 한 번 이상 살아남은 인스턴스들이 위치하는 곳
- servivor1과 2둘 중 하나는 꼭 비어있어하는 규칙이 있다.
Old 영역(Old Generation)
- Young generation에서 살아남은 인스턴스들이 위치하는 곳.
- young 영역보다 메모리가 크게 할당되고 GC가 적게 발생한다.
- young generation에서만 GC가 발생하면 minor GC, Old generation까지 GC가 발생하면 full GC라고 불린다.
스택 영역 (Stack Area)
스택 영역은 메서드의 호출과 관계되는 지역 변수와 매개변수를 저장합니다.
stack은 LIFO 구조로 마지막에 들어온 값이 먼저 나가는 방식이다.
메서드 호출 시마다 각각의 스택 프레임(호출된 메서드만을 위한 공간)이 생성되고 수행이 끝나면 프레임별로 삭제된다.
Heap 영역에서 저장하는 것과 스택 영역에서 저장하는 것에 혼돈이 올 수 있는데
String a = new String("A");
라고 했을 때 new String("A")는 힙 영역, a는 스택 영역에 저장된다.
스택 영역은 스레드마다 존재하며 스레드에 메모리가 충분하지 않다면 StackOverFlow가 발생할 수 있다.
정리
'CS > JAVA' 카테고리의 다른 글
JVM - 클래스 로더(Class Loader) (4) | 2025.08.04 |
---|