스태틱 영역, 스택 영역, 힙 영역, 콜 바이 밸류, 콜 바이 레퍼런스

스태틱 영역, 스택 영역, 힙 영역

 

1. 정적 메모리(스태틱(Static))

모두가 공유하는 전역 변수, Static이 기억되는 장소이다. 프로그램이 끝날 때까지 기억한다.

프로그램이 시작되면 메모리가 할당되어 있으므로 new를 쓰지 않고 사용가능하다. 예를 들면 영원한 디버깅의 친구 System.out.println의 “out”이 스태틱이다. 사실상 영구적으로(영원히!) 기억한다. 즉, 단 하나의 기억공간을 갖는다.

프로그램에서 공통적으로 사용하고 있고, 메모리 공간 1개를 갖는 변수/메소드/객체가 필요하다면 static을 씁시다.

   ※자바의 정석에서는 ‘메소드 영역’이라고 부르는 듯 하다.

 

2. 스택(Stack)

일반적으로 int, double 등으로 편하게 선언하는 변수들이 스택에 들어간다. LIFO, 다시 말해서 후입선출(Last In Fisrt Out)을 따른다. 변수 영역을 벗어나면 휘발된다. 다시 말해, 블록을 벗어날 때까지 기억한다. 참고로 String str=”a”;는 스택에 저장된다.

 

 

3. 동적 메모리(힙(Heap))

자바에서 new를 쓰면 힙에 저장된다. 새로운 것(뉴)는 힙한 것이기 때문이다.(…는 농담이지만 외우기 편하다)

동적 할당이기에 다소 느리지만 메모리에 영원히(!) 올려두는 스태틱과 달리, 필요할 때 메모리에 올렸다가 해제할 수 있는 특징이 있다.

C에서는 malloc과 free를 이용하지만, 자바에서는 new만 쓰면 된다. 왜냐면 gc(가비지 컬렉터)가 임의로 자동 해제시켜주기 때문이다.

참고로 new String(“a”);는 힙에 저장된다.

 

예를 들면 P라는 클래스가 있고, 피 피는 뉴피(P p=new P();) 로 선언했다고 하자. 이 때 오른쪽의 new P()는 힙에 기억됐다. 다만 왼쪽의 소문자 p는 스택에 기억됐다. P p라는 것은 마치 int p와 비슷한 것으로, (클래스가 사용자 정의형(Type)이기 때문에), 대문자 P는 타입이고, 소문자 p는 변수명일 뿐이다. 소문자 p는 int p와 마찬가지로 스택에 저장된다는 소리다. 다시 말해 p는 주소값을 가질 뿐이다. 그 주소값은 new로 만든 클래스 P(new P();)를 가르키게 된다.

 

따라서 P p=new P(); 처럼 선언하지 않고 new P();로만 썼다면 이 인스턴스를 재사용할 수가 없다. 주소값을 기억하는 변수가 없어서 잃어버렸기 때문이다.

 

★. 콜 바이 밸류(값 호출), 콜 바이 레퍼런스(참조 호출)

int, double, char 등을 프리미티브 타입(primitive: 원시의)이라고 한다. 알다시피 프리미티브 타입은 스택에 저장되고, 레퍼런스 타입은 힙에 저장된다. 여기서 스택의 변수(프리미티브 타입)를 갖다쓰면 콜 바이 밸류가 되고, 힙의 객체(레퍼런스 타입)를 갖다쓰면 콜 바이 레퍼런스가 된다.

 

예를 들어 변수 a를 매개변수로 하는 메소드가 있다고 하자. 메소드 내에서 a값을 이리저리 변경해도, 블록을 빠져나가서 a값을 출력하면 반영되어 있지 않다. 값을 가져다가 쓴 것 뿐이기 때문이다. 이를 콜 바이 밸류라 한다.

 

그러나 클래스 P p를 매개변수로 하는 메소드가 있다고 하자. (여기서 소문자 p는 사실상 클래스 P를 가리키는 포인터이다. 주소값을 가지고 있는 스택 변수.) 이때 클래스 P안의 변수 a값을 변경하고,(P.a++;) 블록을 빠져나가서 다른 곳에서 P.a 값을 출력해도 변경사항이 반영되어 있다. 이를 콜 바이 레퍼런스라 한다.