프로그래밍에서 메모리 관리를 이해하는 데 중요한 개념
각 영역은 메모리를 할당하고 관리하는 방식이 다르며, 주로 사용되는 상황도 다름
Stack 영역
함수 호출과 관련된 지역 변수 및 임시 변수들이 저장되는 메모리 공간
LIFO (Last In, First Out) 방식으로 관리
함수가 호출될 때마다 스택 프레임이 생성되며, 함수가 종료되면 해당 스택 프레임이 해제됨
이 프레임에는 지역변수, 매개변수, 리턴주소 등이 저장됨
▶ 특징:
- 빠른 메모리 할당/해제: 스택은 메모리 할당과 해제가 매우 빠름
- 고정 크기: 스택의 크기는 프로그램 시작 시 결정되며, 보통 비교적 작은 크기
- 자동 관리: 함수 호출 시 메모리 할당, 함수 종료 시 메모리 해제가 자동으로 이루어짐
- 지역 변수 저장: 지역 변수와 함수 매개변수는 스택에 저장
▶ 한계:
- 메모리 크기 제한:
스택은 일반적으로 제한된 크기를 가지며,
너무 많은 메서드 호출(특히 재귀 호출)이 발생하면 StackOverflowError가 발생할 수 있음 - 저장되는 데이터의 유형:
스택에는 기본형 데이터(int, float, 등)와 참조형 데이터(객체의 참조)가 저장됨. (실제 객체는 힙에 저장)
public void myMethod() {
int a = 10; // 'a'는 스택에 저장됨
int b = 20; // 'b'도 스택에 저장됨
}
Heap 영역
동적으로 메모리를 할당하는 데 사용되는 공간
프로그램 실행 중에 필요에 따라 메모리를 할당하고 해제할 수 있음
모든 객체와 배열은 힙에 저장되고, 참조변수를 통해 접근가능
>> 객체는 new 키워드를 사용하여 힙에 동적으로 할당됨
▶ 특징:
- 동적 메모리 할당: 런타임에 메모리를 할당하고 필요 없을 때 해제함
- 크기 제한 없음: 스택보다 큰 메모리 블록을 할당할 수 있음
- 수동 관리: 프로그래머가 명시적으로 메모리를 할당하고 해제해야 함 (Java에서는 가비지 컬렉터가 자동으로 관리)
- 가비지 컬렉션: 힙의 메모리는 자동으로 관리, 더이상 참조되지 않는 객체는 가비지컬렉션을 통해 메모리에서 해제
- 객체 저장: 힙은 객체 및 배열과 같은 동적 데이터 구조를 저장하는 데 사용
▶ 한계:
- 메모리 접근 속도: 힙의 메모리 접근은 스택보다 느림
- 메모리 단편화: 힙은 동적으로 메모리를 할당하고 해제하기 때문에 메모리 단편화(fragmentation)가 발생할 수 있음
- 가비지 컬렉션의 오버헤드: 가비지 컬렉션은 메모리를 관리하지만, 실행 시 약간의 오버헤드를 초래할 수 있음
public void myMethod() {
int[] array = new int[10]; // 배열은 힙에 저장됨
String str = new String("Hello, Heap!"); // 문자열 객체도 힙에 저장됨
}
차이점 정리
구 분 | Stack | Heap |
역할 | 메서드 호출과 관련된 메모리 관리 | 동적으로 생성된 객체와 배열의 메모리 관리 |
구조 | LIFO | 비구조적, 동적할당 |
메모리 할당 | 자동 할당 | 동적 할당 (new 키워드 사용) |
메모리 해제 | 메서드 종료 시 자동 해제 | 가비지 컬렉션에 의해 자동 해제 |
저장 데이터 | 기본형 데이터, 참조형 데이터(객체의 참조) | 실제 객체와 배열 |
접근 속도 | 빠름 | 상대적으로 느림 |
메모리 크기 | 제한된 크기 | 유연한 크기 |
장점 | 빠른 메모리 접근 속도, 효율적인 메모리 관리 | 더 큰 메모리 공간, 객체와 배열 관리 용이 |
단점 | StackOverflowError 발생 가능, 제한된 메모리 크기 |
메모리 단편화 가능성, 가비지 컬렉션 오버헤드 |
예외상황 | 너무 많은 메서드 호출 시 StackOverflowError 발생 | 메모리 부족 시 OutOfMemory 발생 |
동적 메모리 할당 dynamic memory allocation
프로그램 실행 단계(런타임)에서 필요한 메모리를 할당하는 것을 의미
컴파일 시점에 메모리 크기가 고정되지 않고 런타임 시점에 필요한 만큼 할당
주로 힙 영역에 저장됨
ArrayList와 같은 동적 배역을 사용할 때 적용
프로그램 실행 중에 필요에 따라 메모리를 할당하고 해제할 수 있음
필요할 때마다 메모리를 할당하고, 더 이상 필요하지 않을 때 해제
▶ 특징:
- 유연성: 프로그램 실행 중에 필요한 메모리 양을 결정할 수 있어, 메모리를 효율적으로 사용할 수 있음
- 런타임 할당: 변수나 객체가 필요할 때 메모리를 할당하고, 더 이상 필요 없을 때 해제함
- 가변 크기: 할당되는 메모리 크기가 고정되지 않고, 필요에 따라 달라질 수 있음
Java에서 동적 메모리 할당은 주로 객체와 배열을 생성할 때 발생
>> new 키워드를 사용하여 객체나 배열을 생성할 때 메모리가 힙 영역에 동적으로 할당됨
// 객체 생성
MyClass obj = new MyClass(); // MyClass 객체가 힙에 동적으로 할당됨
// 배열 생성
int[] arr = new int[10]; // 크기 10인 int 배열이 힙에 동적으로 할당됨
String str = new String("Hello, World!");
// new String("Hello, World!")는 힙에 새로운 String 객체를 동적으로 할당함
정적 메모리 할당 static memory allocation
컴파일 단계에서 메모리 공간을 할당받음
주로 스택영역에 저장됨
지역변수와 매개변수가 이 방식으로 할당됨
함수가 종료될 때까지 메모리가 유지됨
배열을 선언할 때 크기를 미리 지정하는 경우
프로그램 실행 전, 컴파일 과정에서 변수의 메모리 크기와 위치가 결정
int a = 10; // 지역 변수, 스택에 할당됨
static int b = 20; // 정적 변수, 데이터 영역에 할당됨
차이점 정리
특 징 | 동적 메모리 할당 | 정적 메모리 할당 |
할당 시기 | 런타임 (실행 중) | 컴파일 타임 |
메모리 위치 | 힙 | 스택, 데이터 영역 |
크기 | 가변 | 고정 |
할당/해제 | 명시적 (Java는 가비지 컬렉터가 자동 해제) | 자동 |
메모리 관리 | 복잡 (메모리 누수 가능성) | 간단 |
접근 속도 | 상대적으로 느림 | 빠름 |
사용 예 | 객체 생성, 배열 생성 | 지역변수, 전역변수, 정적변수 |
장점 | 유연한 메모리 사용, 큰 데이터 처리 가능 | 빠른 접근 속도, 단순한 관리 |
단점 | 메모리 관리 복잡, 성능 오버헤드 | 크기 변경 불가, 메모리 낭비 가능성 |
'Language > Studying' 카테고리의 다른 글
[Java] Overload와 Override (feat. 다형성) (0) | 2024.07.17 |
---|---|
[Java] Java API (0) | 2024.07.17 |
[Java] ArrayList와 HashMap (0) | 2024.07.08 |
[Java] this와 super (0) | 2024.07.04 |
[Java] 상속(Inheritance) (0) | 2024.07.03 |