JAVA

[JAVA] Static Stack Heap 메모리 구조

개발로 먹고 살자 2022. 1. 6. 16:49

메모리는 프로그램을 구동시키기 위해서 꼭 필요한 것이고, CPU가 처리할 데이터가

임시로 저장되어 있는 공간이다.

 

메모리의 공간이 한정되어 있기 때문에 어떻게 관리하느냐에 따라 성능이 달라진다.

메모리의 공간은 크게 static, stack, heap으로 나뉘어져 있다.

 

하나씩 알아보도록 하자.

 

Static

static 메모리 영역은 필드 부분에 선언된 변수(전역변수)와 static이 붙은 변수와 메소드인

정적 멤버를 static 영역에 저장한다.

static 영역에 저장된 데이터는 프로그램의 시작부터 종료까지 데이터가 남아있다.

정적 메모리를 잘 사용할 경우 메모리의 이점, 공유와 같은 장점이 있지만,

무분별하게 사용할 경우 메모리 부족 문제가 발생할 수 있으며 공유가 되는 자원이기

때문에 멀티쓰레드 환경에서 버그를 불러올 가능성이 있다.

 

사용 예시

public class staticTest {

	static int value = 0; // 정적 변수
	
	public static void test() {} // 정적 메소드
}

 

stack

stack 메모리 영역은 말 그대로 위에서 아래로 쌓아가는 방식의 메모리이다.

메소드 내에 정의되는 기본 자료형을 가진 지역변수의 값이 저장되는 공간이다.

해당 메소드가 호출될 때 메모리에 할당이 되고 메소드가 종료되면 메모리가 사라진다.

 

함수 메모리 공간 예시

public class staticTest {

	public static void test(int value) {
		value = 20;
		System.out.println(value);
	}
	
	public static void main(String[] args) {
		int value = 10;
		System.out.println(value);
		test(value);
		System.out.println(value);
	}
}
------------ 출력 결과 ------------------
10
20
10

value라는 변수를 선언하여 stack 메모리 영역에 올라갔다.

test() 함수를 호출하며 임시 공간에 생기고 value = 20이 stack 영역에 다시 적재된다.

함수가 끝나면 value = 20이 담긴 stack의 메모리 영역이 사라지게 된다.

값이 변경되지 않는 이유는 call by value, call by reference 게시글에 작성했다.

 

또 다른 예시

public class staticTest {
	
	public static void main(String[] args) {
		int value = 10;
		value = 20;
		value = 30;
		value = 40;
		System.out.println(value);
	}
}
---------------- 출력 결과 ------------------
40

stack 메모리 영역은 기본적으로 LIFO(Last In First Out)방식은 따른다.

가장 처음 들어온 데이터가 가장 먼저 나가게 되는 구조이다.

 

그렇기 때문에 value 변수 선언 시 stack 메모리 영역에 10이 적재되어 있고,

value = 20;을 통해 20이 들어가면서 10이 사라진다.

 

지역 변수내 메모리 영역

public class staticTest {
	
	public static void main(String[] args) {
		
		for(int i = 0; i < 5; i++) {
			
		}
		System.out.println(i);
	}
}
----------- 출력 결과 ------------
error

for문이라는 지역 변수내에서 i를 선언하였다.

for문이 시작되며 지역 변수내에서 stack이 할당이 되지만 for문이 끝나면서

stack 영역에서 메모리가 해제되기 때문에 지역 변수밖에서 출력하는

i는 에러가 뜨게 된다.

 

heap

heap은 참조형 데이터 객체의 실제 데이터들이 담기는 공간이다.

public class HeapTest {

	public static void main(String[] args) {
		
		HeapTest heap = new HeapTest();
		
	}

}

new 클래스(); 를 통해 생성된 객체는 heap 영역에 담기게 된다.

이 때 객체를 참조할 수 있는 주소는 객체를 생성할 때 stack 메모리 영역에 생성이 된다.

즉, heap은 참조형 데이터 객체의 실제 데이터들을 가지고 있는 공간이고,

실제 데이터를 참조할 수 있는 참조 주소 값을 stack 메모리 영역이 가지고 있다.

 

public class HeapTest {

	public static void main(String[] args) {

		HeapTest heap1 = new HeapTest();
		HeapTest heap2 = new HeapTest();
		
		System.out.println(heap1);
		System.out.println(heap2);
	}

}
----------- 출력 결과 -----------------
staticTest.HeapTest@15db9742
staticTest.HeapTest@6d06d69c

실제 객체를 생성하였을 경우 서로 다른 heap 공간을 가지고 있는 것을 볼 수 있다.

 

 

그럼 stack 메모리 영역에 heap을 가리키는 참조 주소가 있다는 것을 확인해보겠다.

public class HeapTest {

	public static void main(String[] args) {

		HeapTest heap = null;
		System.out.println(heap);
		heap = new HeapTest();
		System.out.println(heap);
	}
	
}
-------------- 출력 결과 ------------------
null
staticTest.HeapTest@15db9742

우선 HeapTest 라는 객체 타입의 heap을 선언하였다.

이 때 stack 메모리 영역에 공간이 할당되게 된다.

그 후 heap에 new 클래스(); 를 통하여 heap 영역에 실제 데이터 공간을 할당하고

객체 stack 메모리 영역에 있는 heap에 참조 값을 할당하게 된다.

'JAVA' 카테고리의 다른 글

[JAVA] Map - HashMap, TreeMap, LinkedHashMap  (0) 2022.01.12
[JAVA] Collection framework  (0) 2022.01.12
[JAVA] Call by value와 Call by reference  (0) 2022.01.06
[JAVA] 정적 변수, 정적 메소드(Static)  (0) 2022.01.05
[JAVA] 접근제어자  (0) 2022.01.04