🔍 Java에서 힙(Heap)과 스택(Stack) 메모리의 차이점
Java에서 메모리는 크게 힙(Heap)과 스택(Stack) 으로 나뉘며, 각 메모리는 목적과 동작 방식이 다릅니다.
Java 프로그램이 실행될 때 객체와 변수들이 저장되는 위치가 달라지고, 성능에도 영향을 미칠 수 있습니다.
✅ 1. 힙(Heap)과 스택(Stack) 개념
메모리 영역 | 힙(Heap) | 스택(Stack) |
주요 역할 | 객체(Object) 저장 | 메서드 실행 및 지역 변수 저장 |
할당 방식 | 동적 할당 (런타임) | 자동 할당 (메서드 호출 시) |
수명 | GC(Garbage Collection)에 의해 해제됨 | 메서드 실행이 끝나면 자동 해제 |
속도 | 상대적으로 느림 | 상대적으로 빠름 |
저장 대상 | 객체(클래스 인스턴스), 배열 | 기본형 변수, 참조 변수, 메서드 호출 정보 |
메모리 관리 | JVM이 관리 (GC가 정리) | 자동 관리 (메서드 종료 시 해제) |
✅ 2. 힙(Heap) 메모리
📌 힙 메모리란?
- Java에서 생성된 모든 객체(Object)와 배열(Array)가 저장되는 공간.
- new 키워드로 생성한 객체는 모두 힙 메모리에 저장됨.
- GC(Garbage Collector) 가 사용되지 않는 객체를 자동으로 제거하여 메모리를 회수함.
📝 힙 메모리 예제
class Person {
String name; // 힙 메모리에 저장됨
}
public class HeapExample {
public static void main(String[] args) {
Person p1 = new Person(); // 힙 메모리에 객체 저장
Person p2 = new Person(); // 또 다른 객체가 힙에 저장됨
}
}
📌 메모리 동작 과정
- Person p1 = new Person(); → 새로운 객체가 힙(Heap)에 생성됨.
- Person p2 = new Person(); → 또 다른 객체가 힙에 저장됨.
- p1, p2는 객체의 주소를 가리키는 참조 변수(Reference)이며, 스택(Stack) 메모리에 저장됨.
- 사용되지 않는 객체는 GC(Garbage Collector)에 의해 자동으로 제거됨.
✅ 3. 스택(Stack) 메모리
📌 스택 메모리란?
- 메서드 호출 시 생성되는 지역 변수, 매개변수, 참조 변수 등이 저장되는 공간.
- 메서드 실행이 끝나면 해당 메모리는 자동으로 해제됨.
- LIFO(Last In First Out) 구조로 동작함 → 가장 마지막에 호출된 메서드가 먼저 제거됨.
📝 스택 메모리 예제
public class StackExample {
public static void main(String[] args) {
int a = 10; // 기본형 변수 → 스택 저장
int b = 20; // 기본형 변수 → 스택 저장
sum(a, b); // sum() 메서드 호출 → 새로운 스택 프레임 생성
}
public static int sum(int x, int y) {
int result = x + y; // 지역 변수 result → 스택 저장
return result; // sum() 실행이 끝나면 result 변수가 사라짐
}
}
📌 메모리 동작 과정
- main() 실행 → 스택에 main() 프레임 생성.
- a = 10, b = 20 → 스택에 저장됨.
- sum(a, b) 호출 → 새로운 스택 프레임 생성.
- sum() 실행 중 x, y, result 변수가 스택에 저장됨.
- sum() 실행 종료 → sum()의 스택 프레임이 사라지고 메모리 해제.
- main() 실행 종료 → 스택 메모리 해제.
✅ 4. 힙과 스택의 차이점 정리
구분 | 힙(Heap) 메모리 | 스택(Stack) 메모리 |
저장되는 데이터 | 객체, 배열 | 기본형 변수, 참조 변수, 메서드 실행 정보 |
할당 방식 | new 키워드로 생성 (런타임) | 메서드 호출 시 자동 할당 |
수명 | GC(Garbage Collector)가 관리 | 메서드 종료 시 자동 해제 |
속도 | 상대적으로 느림 (GC 개입) | 빠름 (자동 해제) |
메모리 크기 | 크기가 크고 확장 가능 | 제한적 (JVM 설정에 따라 다름) |
예제 | Person p = new Person(); | int x = 10; |
✅ 5. 힙 & 스택 관련 주요 이슈
📌 (1) 메모리 누수 (Memory Leak)
- 힙 메모리에 남아 있는 객체가 GC에 의해 수거되지 못하는 경우 발생.
- 예제:
- list.clear(); 를 사용해 필요 없는 객체를 명확히 제거.
- WeakReference 사용하여 GC가 수거할 수 있도록 유도.
class MemoryLeak {
static List<int[]> list = new ArrayList<>();
public static void main(String[] args) {
while (true) {
list.add(new int[1000000]); // 계속해서 메모리 사용 → GC가 수거 불가능
}
}
}
📌 (2) 스택 오버플로우 (Stack Overflow)
- 무한 재귀 호출로 인해 스택 메모리가 가득 차면 발생.
- 예제:
- 재귀 호출 시 반드시 탈출 조건(Base Case)을 설정.
- 반복문(Loop)으로 대체하여 스택 사용 최소화.
public class StackOverflowExample {
public static void recursiveMethod() {
recursiveMethod(); // 무한 재귀 호출
}
public static void main(String[] args) {
recursiveMethod();
}
}
🎯 결론
- 힙(Heap): 객체 저장 공간 (new 키워드로 생성), GC가 관리, 상대적으로 느림.
- 스택(Stack): 지역 변수 및 메서드 호출 정보 저장, 자동 할당 및 해제, 빠름.
- 힙 메모리 관리를 잘못하면 메모리 누수 발생!
- 스택 사용이 많으면 StackOverflowError 발생 가능!
📌 즉, 힙과 스택을 적절히 활용하여 메모리를 효율적으로 관리하는 것이 중요합니다! 🚀
반응형
'서버&백엔드 > 🔥 JAVA' 카테고리의 다른 글
스레드에서 생성된 메모리 영역은 다른 스레드에서 접근 가능할까? (0) | 2025.02.04 |
---|---|
JAVA | 뮤텍스(Mutex) vs 세마포어(Semaphore) (0) | 2025.02.03 |
Java 병렬 스트림(Parallel Stream) 사용 시 예상되는 문제와 해결 방법 (0) | 2025.02.03 |
JAVA | var 이란? (0) | 2024.12.22 |
JAVA | TDD API 테스트 & 리팩토링 (2) | 2024.12.20 |