메모리 구조(static, stack, heap)
Updated:
메모리 구조(static, stack, heap)
프로그램을 구동하기 위해서 운영체제가 메모리(RAM)에 데이터 및 명령어를 저장할 공간을 할당하여 줍니다.
메모리는 컴퓨터에게 있어서 중요한 자산이고 사용할 수 있는 공간이 한정되어 있습니다. 메모리를 어떻게 관리하느냐에 따라서 프로그램의 성능(속도 등)이 좌우됩니다. 따라서 메모리를 효율적으로 사용하기 위해서는 메모리의 구성과 특징에 대해서 이해할 필요가 있습니다.
메모리의 공간은 크게 Static(스태틱) 영역, Stack(스택) 영역, Heap(힙) 영역으로 구분되고 데이터타입(자료형)에 따라서 해당 공간에 할당됩니다.
Static area(스태틱 메모리 영역)
하나의 JAVA 클래스는 크게 필드(field), 생성자(constructor), 메소드(method)로 구성됩니다.
public class ClassName
{ //필드 : 필드는 객체의 고유 데이터, 부품 객체, 상태 정보를 저장하는 곳입니다.
int fieldName;
//생성자 : 생성자는 new 연산자로 호출되는 특별한 중괄호 {} 블록입니다. 생성자의 역할은 객체 생성 시 초기화를 담당합니다.
ClassName() { ... }
//메서드 : 메서드는 객체의 동작에 해당하는 중괄호 {} 블록을 말합니다.
void methodName() { ... }
}
그중 필드 부분에서 선언된 변수(전역변수)와 정적 멤버변수(static이 붙은 자료형) Static 영역에 데이터를 저장합니다.
Static 영역의 데이터는 프로그램의 시작부터 종료가 될 때까지 메모리에 남아있게 됩니다. 다르게 말하면 전역변수가 프로그램이 종료될 때까지 어디서든 사용이 가능한 이유이기도 합니다. 따라서 전역변수를 무분별하게 많이 사용하다 보면 메모리가 부족할 우려가 있어 필요한 변수만 사용할 필요가 있습니다.
Stack area(스택 메모리 영역)
메소드 내에서 정의하는 기본 자료형(int, double, byte, long, boolean 등)에 해당되는 지역변수(매개 변수 및 블럭문 내 변수 포함)의 데이터의 값이 저장되는 공간이 Stack(스택) 영역입니다. 해당 메소드가 호출될 때 메모리에 할당되고 종료되면 메모리가 해제됩니다.
public class StackArea {
public static void main(String[] args) {
int a = 1; a = 2; a = 3; a = 4;
System.out.println(a); // 4 출력
for(int i=0; i<5; i++){
}
// System.out.println(i); 컴파일 에러
}
}
위의 소스 코드처럼 a라는 변수는 main 메소드가 호출될 때 Stack 영역에 할당되고 종료 시 해제됩니다. 또한 a라는 변수의 값이 1, 2, 3, 4 순으로 값을 할당하였고 출력되는 값은 4가 출력된다. 이전 데이터는 지워지는 것이고 4라는 값만 출력됩니다. 즉, Stack 영역은 LIFO(Last In First Out)의 구조를 갖고 변수에 새로운 데이터가 할당되면 이전 데이터는 지워진다는 것을 알 수 있습니다.
또한 for문 내에 int i를 정의하였는데 for문이 종료된 다음 i를 출력하지 못하는 이유는 지역변수이므로 for문의 종료와 함께 Stack 영역에서 해제되었기 때문입니다.
Heap area(힙 메모리 영역)
참조형(Reference Type)의 데이터 타입을 갖는 객체(인스턴스), 배열 등은 Heap 영역에 데이터가 저장됩니다. 이때 변수(객체, 객체변수, 참조변수)는 Stack 영역의 공간에서 실제 데이터가 저장된 Heap 영역의 참조값(reference value, 해시코드 / 메모리에 저장된 주소를 연결해주는 값)을 new 연산자를 통해 리턴 받습니다. 다시 말하면 실제 데이터를 갖고 있는 Heap 영역의 참조 값을 Stack 영역의 객체가 갖고 있습니다. 이렇게 리턴 받은 참조 값을 갖고 있는 객체를 통해서만 해당 인스턴스를 핸들 할 수 있습니다.
public class HeapAreaEx01 {
public static void main(String[] args) {
int[] a = null; // int형 배열 선언 및 Stack 영역 공간 할당
System.out.println(a); // 결과 : null
a = new int[5]; // Heap 영역에 5개의 연속된 공간 할당 및
// 변수 a에 참조값 할당
System.out.println(a); // 결과 : @15db9742 (참조값)
}
}
public class HeapAreaEx02 {
public static void main(String[] args) {
String str1 = new String("joker");
String str2 = new String("joker");
if(str1 == str2){
System.out.println("같은 주소값 입니다.");
}else{
System.out.println("다른 주소값 입니다.");
}
}
}
문자열을 저장하는 String도 참조형입니다. new 연산자를 이용해서 생성하면 데이터는 Heap 영역에 저장되고 str1과 str2는 참조 값을 리턴 받습니다. 저장된 주소가 다르기 때문에 “==”으로 비교 시 “다른 주소값 입니다.”가 출력되는 것입니다.
class A{}
public class HeapArea {
public static void main(String[] args) {
A a = null; // A타입의 a객체 선언 및 Stack 영역 공간 할당
System.out.println(a); // 결과 : null
a = new A(); // Heap 메모리에 공간 할당 및 객체(a)에 참조값 할당
System.out.println(a); // 결과 : @15db9742
}
}
- 참고로 Heap에 저장된 데이터가 더 이상 사용이 불필요하다면 메모리 관리를 위해 JVM(자바 가상머신)에 의해 알아서 해제됩니다. 이러한 기능을 가비지컬렉션(GC, 쓰레기 수집)이라고 합니다.
Leave a comment