Java 메모리 구조는 크게 3가지로 나뉜다.

코드의 실행 흐름을 시각적으로 확인하려면 아래의 사이트를 이용하면 된다.
직접 보면서 공부해 보자.

// 실행 흐름 확인을 위해 사용한 코드
public class Main {
static class Person {
// 1. 속성
String name;
int age;
String address;
// 2. 생성자
Person(String name, int age) {
this.name = name;
this.age = age;
}
// 3-1. 소개 기능 (이름 나이 출력 기능)
void introduce() {
System.out.println("나의 이름은");
System.out.println(this.name + "입니다.");
System.out.println("나의 나이는");
System.out.println(this.age + "입니다.");
}
// 3-2. 더하기 기능 (소개를 하고 더하기 연산 수행)
int sum(int value1, int value2) {
introduce();
int result = value1 + value2;
return result;
}
}
public static void main(String[] args) {
String name = "Steve";
int age = 20;
Person personA = new Person(name, age);
personA.introduce();
int value1 = 1;
int value2 = 2;
int ret = personA.sum(value1, value2);
System.out.println(ret);
}
}
1️⃣ 프로그램이 실행되면 작성했던 모든 파일(.java)의 데이터가 Method(static) 영역에 저장된다.
2️⃣ 프로그램 실행 시점에 한 번만 저장된다.
3️⃣ Method 영역에 저장된 데이터는 프로그램 전체에서 공용으로 활용 가능하다.
4️⃣ static으로 선언된 변수와 메서드들이 이 공간에 위치한다.
new 키워드로 생성된 객체는 Heap 영역에 저장된다고 한다.
Java Visualizer를 이용해 직접 확인해 보자.

34번 라인과 같이 new 키워드로 객체를 생성하면

그림과 같이 Heap Area (Objects)에 인스턴스가 생성되는 것을 볼 수 있다.
1️⃣ 메서드가 호출될 때마다 Stack 영역에 메모리가 할당된다.
2️⃣ LIFO-후입선출 구조이다. (자료구조 과목에서 지겹도록 나온다.)
3️⃣ 해당 메서드의 정보와 변수가 Stack에 저장되고 메서드 실행이 끝나면 그 메모리는 자동으로 제거된다.

코드만 보고 실행 순서와 메모리 생성/제거 과정을 예상해 보자.
1) sum() 메서드가 실행되어 스택에 추가된다.
2) introduce() 메서드가 실행되어 스택에 추가된다.
3) introduce() 메서드가 모든 기능을 마치고 스택에서 제거된다.
4) 스택에 이미 추가되어 있던 sum() 메서드가 연산을 마치고 값을 반환하며 스택에서 제거된다.
Java Visualizer를 이용한 확인
1번, 2번 과정

3번 과정 (다음 실행 순서에서 제거된다.)

4번 과정 (다음 실행 순서에서 제거된다.)

이정도를 모두 이해하고 나면 하나의 의문이 들 수 있다.
그럼 Heap Area에 저장된 객체는 언제 제거되는 걸까?
Java에선 GC(Gabage Collector)라고 하는 기능으로 Heap Area를 관리한다.
사용하지 않는 객체를 자동으로 제거해 불필요한 메모리 누수를 줄이는 기능이다.
단순하게 말만 들어서는 장점만 존재하는 편리한 기능 같지만 세상의 이치가 그렇듯 단점도 존재한다.
자동으로 메모리를 관리해 준다는 것은 그만큼 가비지 컬렉터를 위한 자원이 상시 소비되고 있다는 뜻이다.
따라서 가비지 컬렉터가 실시간 서비스 품질에 부정적인 영향을 미칠 수도 있다.
(💡참고) 객체지향 언어인 C++에서 new 키워드를 사용해 객체를 생성하게 되면
코드로 직접 delete 하기 전까지는 계속해서 Heap Area에 남아있게 된다.
굳 입니다~