Java 메모리 - 코딩으로 살펴보는 스택과 힙 영역 변화
다음 코드를 작성한다.
Data.java
package pack;
public class Data {
private int value;
public Data(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
JavaMemory.java
package pack;
public class JavaMemory {
public static void main(String[] args) {
System.out.println("main Start");
method1();
System.out.println("main End");
}
static void method1() {
System.out.println("method1 Start");
Data data = new Data(10);
method2(data);
System.out.println("method1 End");
}
static void method2(Data data) {
System.out.println("method2 Start");
System.out.println("method2 End");
}
}
위 코드를 실행 시 다음과 같이 동작한다.
- main() -> method1() -> method2() 순서로 호출하는 코드이다.
- method1() 에서 Data 클래스의 인스턴스를 생성
- mathod1() 에서 method2() 호출 시 매개변수가 Data 인스턴스의 참조 값을 전달하였다.
그림을 통해 알아보기
main() 실행
- 먼저 main() 메소드를 실행하여 main() 메인 프레임을 생성한다.

method1() 호출
- main() 에서 method1() 실행. method1() 스택 프레임이 생성된다.
- method1() 지역 변수로 Data 를 갖고 스택 영역에 있다.
- new Data(10) 코드를 실행하면 힙 영역에서 인스턴스 생성한다. 그리고 참조 값을 data 에 보관한다.

method2() 호출
- method1() 메소드가 method2() 메소드로Data 참조 값을 할당하여 호출한다.
- method1() 에 있는 data 와 method2() 지역 변수는 같은 x00000001 인스턴스를 참조한다.

method2() 반환
- method2() 종료되고 스택프레임과 함께 매개변수 data 참조 값이 제거된다.
- method2()의 data 참조 값이 제거되었지만 heap 영역에 있는 것은 지워지지 않는다. method1() 메소드가 아직 참조하고 있기 때문이다.

method1() 반환
- method1() 종료되고 스택프레임과 함께 매개변수 data 참조 값이 제거된다.
- method1()의 data 참조 값이 제거되었지만 heap 영역에 있는 것은 참조 값을 없어 가비지 콜렉션이 자동으로 제거할 것이다.

main() 반환
- heap area 에 있는 data의 x00000001 데이터는 인스턴스를 참조하는 곳이 없다.
- 사용하지 않는 객체로 보고 가비지 콜렉션이 삭제한다.
- main() 메인 스택이 삭제되면 프로그램을 종료한다.
💡
참고. heap 영역의 객체가 여러개 있고 서로 참조중인 경우는 어떻게 될까?
참조 값은 heap 영역에서만 서로 참조하고 있다 하더라도 stack 영역과 연결된 참조가 없으면 가비지 콜렉션은 heap 에 있는 참조 값을 무시하고 제거한다.
참조 값은 heap 영역에서만 서로 참조하고 있다 하더라도 stack 영역과 연결된 참조가 없으면 가비지 콜렉션은 heap 에 있는 참조 값을 무시하고 제거한다.