JVM 스택은 메소드를 호출할 때마다 프레임을 추가(push)하고, 메소드가 종료되면 해당 프레임을 제거(pop)하는 동작을 수행
프레임 내부에는 로컬 변수 스택이 있는데, 기본 타입 변수와 참조 타입 변수가 추가되거나 제거된다.
스택 영역에 변수가 생성되는 시점은 초기화가 될 때, 즉, 최초로 변수에 값이 저장될 때임
변수는 선언된 블록 안에서만 스택에 존재하고 블록을 벗어나면 스택에서 제거됨
JVM 스택 영역 아래는 main함수 내에서 함수의 호출이 이뤄졌으므로 메인 스레드에서 프레임이 생성된다. 스레드 n에서 함수의 호출이 이뤄지면 스레드-n에서 프레임이 생성된다.
다음과 같이 배열 변수인 scores는 스택 영역에 생성되지만 실제 10, 20, 30을 갖는 배열은 힙 영역에 생성됨. 배열 변수인 scores에는 배열의 힙영역의 주소가 저장됨. 참고로 자바에서는 배열을 객체로 취급함
int[] scores = {10, 20, 30};
정리하자면 메소드가 호출되면 JVM스택에는 프레임이 들어가고 프레임 안에는 여러 변수가 있다. 기본 타입의 경우는 변수 자체에 저장되지만, 참조 타입은 힙 영역에 객체로 생성되며 변수는 힙 영역에 생성된 객체의 주소값을 참조하고 있다. 메소드가 종료되면 JVM 스택에서 프레임이 제거된다. 힙 영역에서 객체를 참조하는 변수가 하나도 없다면 Garbage Collector가 객체를 수거한다.
참조 타입 변수들 간의 ==, != 연산은 동일한 객체를 참조하는지, 다른 객체를 참조하는지 알아볼 때 사용됨 참조 타입 변수의 값은 힙 영역의 객체 주소이므로 ==, != 연산은 결국 주소 값을 비교하는 것이 됨 동일한 주소값을 갖고 있다는 것은 동일한 객체를 참조한다는 의미 반대로 다른 주소값을 갖고 있다는 것은 다른 객체를 참조한다는 의미
참조 타입 변수는 힙 영역의 객체를 참조하지 않는다는 뜻으로 null값을 가질 수 있음. null값도 초기값으로 사용할 수 있기 때문에 null로 초기화된 참조 변수는 스택 영역에 생성됨 참조 변수가 만약 null을 가지고 있을 경우, 참조 객체가 없으므로 변수를 통해 객체를 사용할 수 없음. 따라서 만약 null 상태에서 있지도 않은 객체의 데이터나 메소드를 사용하는 코드를 실행하면 NullPointerException이 발생함
문자열을 String 변수에 저장한다는 말은 엄밀히 말해 틀린 표현이다. 문자열이 직접 변수에 저장되는 것이 아니라, 문자열은 String 객체로 생성되고 변수는 String 객체를 참조하기 때문 자바는 문자열 리터럴이 동일하다면 String 객체를 공유하도록 되어 있음 다음과 같은 경우는 동일한 String 객체를 참조하게 됨
String A = "ReBugs";
String B = "ReBugs";
일반적으로 변수에 문자열을 저장할 경우에는 문자열 리터럴을 사용하지만, new 연산자를 사용해서 직접 String 객체를 생성시킬 수도 있음 new 연산자는 힙 영역에 새로운 객체를 만들 때 사용하는 연산자로 객체 생성 연산자라고 함
String A = new String("ReBugs");
String B = new String("ReBugs");
이 경우는 A와 B는 서로 다른 객체를 참조하고 있다.
따라서 동일한 String 객체이건 다른 String 객체이건 상관없이 내부 문자열을 비교하고 싶을 때는 String 객체의 equals()메소드를 사용해야 함 equals() 메소드는 원본 문자열과 매개값으로 주어진 비교 문자열이 동일한지 비교한 후 true 또는 false를 리턴함