객체를 생성했을 때,
각 세 영역에 어떤 변화가 있는지 알아보자.
자, 그럼 new Clazz().
클래스에 대한 정적 정보가 저장된다.
// 클래스 구조 정보
class Clazz() {
// 정적 변수
public static boolean staticVar;
// 필드 정보
private String name;
private int number;
// 메서드 정보
public void clazzMethod() {
...
}
}
인스턴스는 참조 값을 통하여 접근할 수 있다.
static 변수, 메서드는 클래스 이름을 통하여 바로 사용한다.
따라서 static 메서드에는 참조 값이 생성 되지 않은 인스턴스에 접근할 수 없다.
class Clazz() {
public static int staticNum = 0;
public int instanceNum = 0;
public static void staticMethod() {
staticNum++; // 메서드 영역, 가능
instanceNum++; // 참조 값이 없어 어떤 객체의 instanceNum을 변경해야 할지 모름, Compile Error
}
}
static 변수는 클래스, 인스턴스를 통해서 모두 접근 가능하다.
class Clazz() {
public static int number = 0;
}
public void staticMethod() {
Clazz clazz = new Clazz();
// 클래스 접근
Clazz.number++; // number = 1
// 인스턴스 접근
clazz.number++; // number = 2
스택 영역에는 메서드 호출마다
스택 구조로 메서드 정보가 쌓인다.
메서드 호출이 끝나면, 메서드 호출 정보와 함께 사라진다.
스택 영역의 메서드 내부에서 객체를 생성하면
힙 영역에 실제 객체 인스턴스가 생성되고
메서드 호출이 끝나는 경우 힙 영역에 생성된 실제 객체 인스턴스는
GC(Garbage Collection)의 대상이 되어 사라진다.
동적으로 관리되는 영역이다.
메서드 영역과 힙 영역은 Thread 간 공유하므로
정적(static) 변수, 실제 객체 인스턴스(참조 값은 스택 영역에 각각 별도 생성)는
중복으로 생성하지 않고 접근하게 된다.
메서드, 스택, 힙 영역에서 관리되는 요인들을 이해하고
객체 생성 시에 동작 원리를 머릿 속에 그려보자.
static 변수와 메서드를 선언하고 사용하는 것에 고민해보자.