글 작성자: 개발자 올라프

개요

모든 프로그램은 메모리에 올라와야 실행할 수 있다. 프로그램이 실행되면 JVM은 OS로부터 메모리를 할당받고, 그 메모리를 용도에 따라서 여러 영역으로 나누어 관리를 한다. Java에서 내가 작성한 코드들이 어떤 영역에서 다뤄지는지 알아보기 위해서 정리한다.

 

  • Static 영역
  • Stack 영역
  • Heap 영역

 


 

0. 변수의 종류

메모리 영역을 알기 전에 선언위치에 따른 변수의 종류를 먼저 알아보자

변수는 세 종류로 변수의 선언된 위치에 따라서 클래스변수, 인스턴스변수, 지역변수가 있다.

 

 

멤버변수 중 static이 붙은 것은 클래스변수, 붙지 않은 것은 인스턴스변수이며,

멤버변수를 제외한 나머지는 모두 지역변수이다.

각 변수의 생성시기는 아래와 같다.

  • 클래스변수 : 클래스가 메모리에 올라갈 때
  • 인스턴스변수 : 인스턴스가 생성되었을 때
  • 지역변수 : 변수 선언문이 수행되었을 때

 

클래스변수는 모든 인스턴스가 공통된 저장공간, 값을 유지하는 경우 선언한다. 특징으로는 인스턴스변수와 다르게 객체를 생성하지 않고 바로 사용할 수 있다. 객체생성없이 바로 사용 가능한 이유는 클래스가 메모리에 로딩될 때 생성되어 프로그램이 종료될 때 까지 유지되기 때문이다.

 

인스턴스변수는 클래스의 인스턴스를 생성할 때 만들어지기 때문에 인스턴스를 생성해야 변수의 값을 읽고 저장할 수 있다.

 

지역변수는 메서드 내에 선언되어 메서드 내에서만 사용이 가능하며, 메서드가 종료되면 같이 소멸되어 사용할 수 없게 된다. 예를 들어서 for문, if문 안에서 다뤘던 변수들은 블럭을 벗어나게 되면 소멸되어 메서드 밖에서 사용할 수 없다.

 


 

1. Static Area

- Method Area, Code Area, Class Area 등의 이름을 갖고 있다.

 

JVM이 동작해서 클래스가 로딩될 때 생성된다. 위 그림 중에서 앞에 static이 붙은 클래스 변수인 cv가 Static Area에 저장된다. 앞서 말했듯이 클래스가 메모리에 올라갈 때 이미 자동적으로 생성되기 때문에 클래스 변수들은 인스턴스를 생성하지 않아도 사용이 가능하다는 특징이 있다.

 

하지만 클래스 영역에 선언된 메서드들은 인스턴스 변수를 사용하지 못한다는 단점이 있다. 인스턴스변수는 인스턴스가 생성되어야 사용할 수 있는데 클래스메서드는 인스턴스 생성 없이 바로 호출되었으니 인스턴스가 존재하지 않을 수 있기 때문이다.

 


 

2. Stack Area

메서드의 작업에 필요한 메모리 공간을 제공한다. 메서드가 호출되면 호출스택에 호출된 메서드를 위한 메모리가 할당되며, 메서드가 작업을 수행하는 동안 지역변수들과 연산의 중간결과 등을 저장하는데 사용된다. 그리고 메서드가 작업을 마치면 할당되었던 메모리공간은 반환되어 비워진다.

  • 지역변수, 파라미터, 리턴값, 연산 등 임시값이 생성되는 영역
public class StackArea {
	public static void main(String[] args) {
    	stackMethod();
	}

	static void stackMethod() {
		System.out.println("Hello");
	}
}

 

위 코드가 어떠한 과정으로 진행되는지 그림으로 그려보자.

stack은 쌓아서 채운다는 의미를 갖고 있다. 바구니에 코드 진행순서에 따라 메서드가 쌓였다가 작업을 마치면 빠져나간다고 생각하면 된다.

 

추가로 이 Stack 영역 내에서 메서드가 쌓이고 작업을 다 마쳐가는 순간까지도 Static 영역에 선언된 것은 여전히 존재하고 있음을 잊지말자.

 


 

3. Heap Area

인스턴스가 생성되는 공간으로 프로그램 실행 중에 생성되는 인스턴스는 모두 이곳에 생성된다.

즉, new 키워드로 생성된 객체와 배열이 저장되는 영역이다.

class Data {
	int x;
}

public class HeapArea {
	public static void main(String[] args) {
    	Data d = new Data();
        d.x = 10;
    }
}

이제 위 코드가 메모리 영역에 어떻게 저장될지 Stack영역과 함께 생각해야 한다.

Heap 영역은 Stack 영역과 다르게 보관되는 메모리가 호출이 끝나더라도 삭제되지 않고 유지된다.

Heap 영역에 보관되는 메모리가 삭제되는 시기는 본인을 참조할 변수가 없어져 GarbageCollector에 의해서 삭제되거나 JVM이 종료되면 사라진다. 즉, 본인의 주소를 기억하고 사용해줄 누군가 없어지기 전까지는 유지된다는 것이다.