본문 바로가기
  • hello world
Language/Studying

[Java] Heap 영역과 Stack 영역 (feat. 동적할당, 정적할당)

by JJoajjoa 2024. 7. 16.

 

프로그래밍에서 메모리 관리를 이해하는 데 중요한 개념
각 영역은 메모리를 할당하고 관리하는 방식이 다르며, 주로 사용되는 상황도 다름

 

 

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