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 에 있는 참조 값을 무시하고 제거한다.