반응형
1. 메모리의 두 가지 주요 영역
C#과 같은 언어에서 메모리는 크게 두 가지 영역으로 나뉩니다:
- 스택(Stack): 메서드 호출과 로컬 변수, 값 타입의 데이터를 저장하는 공간.
- 힙(Heap): 동적으로 할당된 객체와 참조 타입의 데이터를 저장하는 공간.
2. 스택(Stack)
특징
- 값 타입 데이터를 저장합니다. (예: int, float, struct 등)
- 메서드 호출 시, 메서드 내에서 선언된 로컬 변수들이 저장됩니다.
- LIFO (Last In, First Out) 구조로 동작합니다.
- 메모리 할당 및 해제가 빠릅니다.
- 스택 메모리는 메서드가 종료되면 자동으로 정리됩니다.
저장되는 데이터
- 값 타입의 데이터 (int, float, bool, etc.)
- 참조 타입의 참조(주소) (객체의 실제 데이터는 힙에 저장).
예시
void MyMethod(){
int number = 10; // 값 타입, 스택에 저장
float price = 20.5f; // 값 타입, 스택에 저장
}
스택 동작
- 메서드가 호출되면, 스택에 **새로운 프레임(frame)**이 생성됩니다.
- 프레임 안에는 메서드의 변수와 데이터가 저장됩니다.
- 메서드가 종료되면, 해당 프레임은 스택에서 제거됩니다.
3. 힙(Heap)
특징
- 참조 타입 데이터를 저장합니다. (예: class, object, string, 배열 등)
- 메모리 할당이 동적으로 이루어집니다.
- 힙의 메모리는 **가비지 컬렉터(Garbage Collector, GC)**가 관리합니다.
- 메모리 할당 및 해제가 스택보다 느립니다.
저장되는 데이터
- 참조 타입의 실제 데이터.
- 참조 타입의 필드 (내부 값 타입 데이터도 힙에 포함됩니다).
예시
void MyMethod()
{
var obj = new MyClass(); // 객체가 힙에 저장됨
obj.Name = "John"; // 필드 데이터도 힙에 저장됨
}
힙 동작
- new 키워드를 통해 객체가 생성되면, 힙에 메모리 공간이 할당됩니다.
- 객체를 참조하는 변수는 스택에 저장되고, 힙에 있는 데이터의 주소를 참조합니다.
- 참조가 끊어진 객체는 GC가 자동으로 정리합니다.
4. Stack과 Heap의 차이
특성 StackHeap
저장 데이터 | 값 타입 데이터, 참조 타입의 주소 | 참조 타입의 실제 데이터 |
메모리 크기 | 상대적으로 작음 | 상대적으로 큼 |
속도 | 빠름 (LIFO 구조) | 느림 (동적 할당) |
메모리 해제 | 자동 (메서드 종료 시 제거) | GC가 자동으로 해제 |
관리 방식 | 정적 (고정 크기, 스코프 기반) | 동적 (필요 시 메모리 확장 가능) |
5. 스택과 힙의 상호작용
참조 타입의 저장 방식
class MyClass
{
public int Value;
}
void MyMethod()
{
var obj = new MyClass(); // 힙에 객체 생성
obj.Value = 42; // 힙의 객체 데이터 수정
}
- 스택: obj 변수에는 힙에 생성된 객체의 주소가 저장됩니다.
- 힙: MyClass 객체와 그 필드(Value)가 저장됩니다.
참조 변경
var reader = new MyClass() { Value = 10 };
var inReader = new MyClass() { Value = 20 };
reader = inReader; // reader는 이제 inReader의 주소를 참조
- 기존 reader가 참조하던 객체는 아무도 참조하지 않으므로, GC가 처리 대상이 됩니다.
- 이후 reader와 inReader는 동일한 객체를 참조합니다.
6. 가비지 컬렉션(GC)
역할
- 힙에서 더 이상 사용되지 않는 객체를 탐지하고 메모리를 해제합니다.
- 프로그래머가 직접 메모리 관리를 하지 않아도 되도록 자동으로 동작합니다.
작동 원리
- GC는 Mark-and-Sweep 알고리즘을 사용합니다:
- Mark: 더 이상 참조되지 않는 객체를 탐지.
- Sweep: 탐지된 객체를 메모리에서 제거.
- GC는 앱 실행 중 메모리가 부족하거나 시스템이 필요하다고 판단할 때 실행됩니다.
7. 메모리 관리에서 주의할 점
- 참조를 명확히 관리:
- 참조를 끊지 않으면 객체가 메모리를 계속 차지하여 메모리 누수가 발생할 수 있습니다.
- Dispose 패턴 사용:
- 파일, 네트워크 연결 등 힙 메모리 외의 리소스를 사용하는 객체는 IDisposable 인터페이스를 구현하여 명시적으로 해제해야 합니다.
- 큰 객체 관리:
- 큰 객체는 **Large Object Heap (LOH)**에 저장되며, GC에서 다르게 처리됩니다. 큰 객체의 사용을 최소화하거나, 분리된 메모리 관리 전략을 고려하세요.
8. 결론
- 스택: 빠르고 자동으로 관리되는 값 타입 데이터 저장 공간.
- 힙: 동적으로 할당되며, GC에 의해 관리되는 참조 타입 데이터 저장 공간.
- 올바른 메모리 관리는 성능 최적화와 안정적인 애플리케이션 개발의 핵심입니다.
반응형
'Java' 카테고리의 다른 글
CPU 바운드 작업 vs 비동기 I/O 작업 (2) | 2024.10.02 |
---|---|
Java, Intelij,JetBrains Toolbox 다운로드 (0) | 2023.07.27 |
Java 컬렉션 프레임워크 LinkedList vs ArrayList (0) | 2023.01.14 |
Java_String toString() 메소드 (0) | 2022.12.30 |