You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
자바 어플리케이션 실행 시작시 할당되는 JVM의 메모리 영역은 실행하는동안 필요한 메모리를 몇 개의 데이터 영역으로 나눠 관리 합니다.
JVM은 다음과 같은 런타임 데이터 영역들로 구성됩니다.
가장 중요한 점은...
모든 쓰레드가 공유하는 영역과 / 공유하지 않는 영역을 구분하는 것이 핵심입니다.
또한 각 쓰레드는 각자 메서드를 실행 한다는 것을 잊어버리면 안됩니다.
1. 프로그램 카운터 레지스터
현재 실행중인 바이트코드 명령어의 줄 번호(주소)를 저장합니다. (Thread private)
즉, 각 쓰레드가 실행할 명령어의 주소를 저장합니다.
1. 현재 실행중인 바이트코드의 명령어를 저장합니다.
JVM의 바이트코드 인터프리터는 이 카운터의 값을 바꾸어 다음에 실행할 명령어를 선택합니다.
2. 스레드 프라이빗: 스레드마다 PC 레지스터를 갖습니다.
JVM에서 멀티스레딩은 한 코어를 스레드가 교대로 사용하게 되는데, 스레드 전환시 멈춘 지점을 찾아 가려면 스레드가 각각의 PC가 필요합니다.
스레드가 실행 될 때마다 생성되고 종료될때 삭제가 됩니다.
2. JVM 스택
메소드 호출과 관련된 정보를 저장합니다. (Thread private)
1. 스레드와 함께 생성/소멸
스택 또한 스레드 프라이빗 하며, 연결된 스레드와 생명주기가 일치합니다.
2. 스택 프레임 생성
JVM은 메서드가 호출될 때 마다 "스택프레임"을 만들어 지역변수 테이블, 피연산자 스택, 동적 링크, 메서드 반환 주소 들을 저장합니다.
만들어진 스택 프레임을 JVM 스택에 호출시 Push, 종료시 Pop 을 반복합니다.
1. 지역 변수 테이블: 메서드 안에서 선언된 지역 변수와 매개변수, 반환 주소 타입 등을 저장하는 공간
-> 컴파일 타임에 지역 변수 슬롯의 크기를 알아내 할당함
3. 피연산자 스택: 바이트코드 명령이 계산에 잠시 사용하는 스택 (CPU의 레지스터 대신 JVM은 스택을 이용해 연산을 수행합니다.) -> a + b를 계산할때 a와 b를 피연산자 스택에 올려 두고 계산
4. 동적 링크: 다른 메서드·필드 참조 정보
5. 메서드 반환 주소: 메서드가 끝나고 다시 돌아갈 위치(호출한 곳의 다음 명령 주소) 저장
3. JVM 스택 메모리 영역에서 발생할 수 있는 오류
StackOverflowError: 스레드가 요청한 스택의 깊이가 JVM이 허용하는 깊이보다 깊다면 발생합니다. OutOfMemoryError: 동적으로 스택 용량을 확장할수 있는 가상머신에서 메모리가 부족하면 발생합니다. (클래식 VM에서 발생할 수 있지만, 최신 핫스팟 VM에서는 동적으로 늘릴수 없기 떄문에 발생하지 않습니다.)
3. 네이티브 메서드 스택
네이티브 코드를 실행하기 위한 스택으로, 네이티브 메소드 호출에 필요한 정보를 저장합니다. (Thread private)
JVM 스택과 비슷하지만, JVM 스택은 자바 메서드(바이트코드)를 실행할때 사용하고, 네이티브 메서드 스택은 네이티브 메서드를 실행할 때 사용합니다.
네이티브 메서드란?
-> 자바가 아닌 다른 언어(C/C++)로 작성된 코드를 말합니다.
4. 힙
모든 스레드가 공유하며, 자바 객체 인스턴스가 이 영역에 저장됩니다.
JVM 구동시 할당되는 영역이며, 모든 자바 객체와 배열은 힙에 할당됩니다.
1. 가비지 컬렉터가 관리
힙은 가비지 컬렉터가 관리하며, 더 이상 참조되지 않는 객체를 찾아서 메모리를 회수합니다.
2. 힙 공간의 분리
1) New Generation
새로 생성된 객체가 저장되는 공간
영역
역할
Eden Space
새로 생성된 객체가 처음 저장되는 공간
Survivor Space 0 (S0)
Eden에서 살아남은 객체가 임시 이동
Survivor Space 1 (S1)
다음 GC 시 교대로 사용 (S0 ↔ S1 전환)
대부분의 객체는 금방 쓰이고 버려집니다.
Minor GC가 자주 발생하여 빠르게 청소합니다.
생존한 객체는 Survivor → Old Generation으로 점진적 이동합니다.
2) Old Generation
여러 번의 GC를 거쳐 살아남은 오래된 객체가 저장되는 공간
전역 객체, 캐시 객체 등 장기간 유지되는 데이터 저장합니다.
Young Generation보다 크기가 크고, GC 발생 빈도는 적습니다.
-> 하지만 한 번의 GC 비용이 큼 → 이를 Major GC 또는 Full GC라 합니다.
3) Permanent Generation
클래스의 메타데이터(클래스 정보, 메서드, 상수풀 등)가 저장되는 영역.
Java 8부터는 Perm Generation이 Metaspace로 대체되어 힙 밖에서 관리가 됩니다.
5. 메서드 영역 (Method Area)
클래스 수준의 메타데이터를 저장하는 공간으로, 모든 스레드가 공유합니다.
JVM이 클래스를 로드할 때, 클래스에 대한 **구조적 정보(메타데이터)**를 이 영역에 저장합니다.
즉, 프로그램 전체에서 한 번만 로드되는 클래스 정보들이 들어 있습니다.
(클래스 로더가 클래스 파일을 읽어 오면 클래스 정보(메타데이터)를 파싱해서 모든 쓰레드가 공유하는 메서드 영역에 저장)
1. 저장되는 내용
구분
설명
클래스 정보(Class Metadata)
클래스의 이름, 부모 클래스, 접근 제어자, 인터페이스 구현 정보 등
런타임 상수 풀(Runtime Constant Pool)
상수, 리터럴, 메서드/필드 참조 등 컴파일 시 결정된 심볼 정보를 저장
정적 변수(Static Variables)
클래스 레벨에서 공유되는 static 필드
메서드 코드(Method Code)
메서드의 바이트코드 명령어, 메서드 관련 메타데이터
2. 스레드 공유
모든 스레드가 공유하는 메모리 영역입니다.
JVM이 로드한 클래스마다 단 한 번만 메서드 영역에 로드됩니다.
클래스가 언로드(unload)되면 관련 데이터도 메서드 영역에서 제거됩니다.
3. 메서드 영역과 런타임 상수 풀의 관계
메서드 영역 내부에는 런타임 상수 풀(Runtime Constant Pool) 이 포함되어 있습니다.
런타임 상수 풀은 클래스 파일의 상수 풀(Constant Pool)을 JVM이 메모리로 로드한 영역으로,
리터럴("Hello")이나 심볼 참조(MyClass.myField) 등을 저장합니다.
→ 실행 중에도 동적으로 상수가 추가될 수 있습니다 (예: String.intern()).
4. PermGen → Metaspace 변화
Java 버전
이름
위치
특징
Java 7 이하
Permanent Generation (PermGen)
힙 내부
크기 고정, OOM 발생 위험
Java 8 이상
Metaspace
힙 외부 (Native Memory)
OS가 관리, 자동 확장 가능
즉, 메서드 영역의 구현체가 PermGen → Metaspace로 바뀐 것입니다.
개념은 같지만, 관리 방식이 개선되었습니다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
키워드
All reactions