이번에는 스택 영역과 힙 영역이 함께 사용되는 경우를 알아보자.
Data
package memory;
public class Data {
private int value;
public Data(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
JavaMemoryMain2
package memory;
public class JavaMemoryMain2 {
public static void main(String[] args) {
System.out.println("main() 메서드 시작");
method1();
System.out.println("main() 메서드 끝");
}
static void method1() {
System.out.println("method1() 메서드 시작");
Data data1 = new Data(10);
method2(data1);
System.out.println("method1() 메서드 종료");
}
static void method2(Data data) {
System.out.println("method2() 메서드 시작");
System.out.println("method2() 메서드에서 data의 값: " + data.getValue());
System.out.println("method2() 메서드 종료");
}
}
main() 메서드 시작
method1() 메서드 시작
method2() 메서드 시작
method2() 메서드에서 data의 값: 10
method2() 메서드 종료
method1() 메서드 종료
main() 메서드 끝
main() --> method1() --> method2() 순서로 호출하는 단순한 코드이다.
method1() 에서 Data 클래스의 인스턴스를 생성한다.
method1() 에서 method2() 를 호출할 때 매개변수에 Data 인스턴스의 참조값을 전달한다.
Data 클래스의 인스턴스가 생성되면 생성된 인스턴스는 힙 영역에 저장이되면서 참조값을 스택 영역에 알려주게 된다.
그래서 method1() 과 method2() 에서 data 라는 값을 스택에 저장할 때, 참조값을 저장하게 되는 것이고, 힙 영역에는 데이터의 값이 저장되는 것이다.
method2() 가 제거되면 스택에서 참조하고 있는 data 의 값이 제거가 되어 method1() 에 있는 data 만 인스턴스의 참조값을 가지게 될 것이다.
method1() 도 제거가 되면 main() 으로 돌아오면서 더 이상 힙 영역에 있는 참조값의 데이터를 사용하지 않게 되는 것이다.
이러면 GC(가비지 컬렉션)이 참조가 모두 사라지면 힙 영역에 있는 이 데이터도 제거한다.
참고: 힙 영역 외부가 아닌, 힙 영역 안에서만 인스턴스끼리 서로 참조하는 경우에도 GC의 대상이 된다.