1️⃣ 메모리의 구조
- JVM 이란 ?
- VJM이란 ? 바이트코드를 해석하고 자바 프로그램을 실행시키는 역할
- JAVA의 메모리 구조는 크게 3가지로 나뉨.
1. Method Area
- 프로그램 시작 시 한번만 클래스 정보가 저장
- 클래스 정보(
.class 파일
) 가 올라가는 곳. - 클래스의 메서드 정보,
static
변수 등이 저장됩니다. - 모든 객체가 공유하는 공용 공간
2. Stack Area
- 가장 위에 있는 접시를 먼저 꺼내듯 비슷한 구조로 생각하기
- 선입후출(LIFO) 구조 입니다. 먼저 들어온 것이 가장 늦게 나간다는 뜻
- 메서드가 호출될 때마다 새로운 스택프레임이 쌓인다.
- 가장 위의 스택인 최근 호출된 메서드가 먼저 실행된다.
- 메서드 실행이 끝나면 스택에서 제거된다.
- 메서드 실행 시 생성되는 지역 변수(Primitive Type, Reference Type 포함)가 저장됨.
- 메서드 호출이 끝나면 해당 스택 프레임이 제거됨.
- 지역 변수(로컬 변수)나 메서드의 매개변수는 Stack에 저장됨.
- -
- 메서드가 호출될 때마다
Stack
영역에 메모리가 할당된다. - 메서드가 시작되면 추가되고 메서드가 종료되면 사라지는 구조이다.
- 특정 메서드가 실행되면 해당 메서드의 정보와 변수가
Stack
에 저장되고 메서드 실행이 끝나면 그 메모리는 자동으로 제거된다. - 메서드 내에 선언된 지역변수들이 저장되는 공간이다. → 변수에 객체가 담기면 객체의 주소값이 저장됨.
3. Heap Area
new
키워드로 생성된 객체(인스턴스)가 저장되는 공간입니다.- 객체의 실제 데이터가 저장되고 데이터의 주소는
stack
영역에 저장됩니다. - new 키워드를 사용하여 생성한 객체는 Heap에 할당된다.(참조 변수(Reference Variable)는 Stack에 저장됩니다.)
- Heap 영역의 객체는 필요 없어지면 가비지 컬렉터(GC)가 정리 가능
2️⃣ 코드의 흐름 살펴보기
- 코드의 흐름을 살펴보기 위해서 아래의 사이트를 이용할 것이다.
"https://cscircles.cemc.uwaterloo.ca/java_visualize/"
Frames 는 Stack 영역,
Object 는 Heap 영역이라고 보면 된다.
- 아래의 코드의 흐름을 분석해보겠다.
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. String name = "Steve";
- 항상 Main
클래스가 먼저 실행된다 생각하면 된다.
Main
의 첫번째 줄인 String name = "Steve";
가 가장 먼저 실행될 것이다.
- 이렇게 보면 "Steve" 라는 값이 Stack[Frame] 영역에 쌓인 걸 볼 수 있다.
- name 자체는 "Steve"를 참조하는 지역 변수이므로 Stack에 저장된 것이다.
>> 이부분을 조금 더 이해하자면,
- 우리가
String name = "Steve";
라고 하면, "Steve"라는 문자열 값이 생기고,name
변수가 그것을 가리키게(참조하게) 된다. - 그래서 우리가 name 을 참조변수라고 얘기를 할 수 있는 것이고, 이 참조변수는 main 메서드가 실행될 시에 Stack 영역에 쌓이게 되는 것이다.
2. int age = 20;
- int age
도 Stack 영역에 쌓인것을 확인할 수 있다.
- 기본형(int)은 값 자체가 Stack에 저장된다.
3. Person personA = new Person(name, age);
- 메서드를 호출 했기 때문에 코드 10줄로 가게된다.
- 새로운 스택 프레임이 쌓이게 되며, 생성자에 따라 Heap 영역에 데이터를 저장하게 된다.
Person(String name, int age) {
this.name = name;
this.age = age;
}
- 코드에서 보다시피, 이전에 할당했던 name과 age의 값을 personA 인스턴스가 참조하여 사용한다.
4. personA.introduce();
- 해당 메서드를 부름으로써 out put 으로 아래와 같이 나온 것을 확인 할 수 있다.
- 이때 힙 영역에 있던 Person instance
를 가져오는 것을 알 수 있다.
5.int value1 = 1; int value2 = 2;
- 마찬가지로, int형 이기 때문에 stack 에 쌓인 걸 볼 수 있다.
6. int ret = personA.sum(value1, value2);
- 해당 sum
메서드를 호출 했기 때문에, 해당 메서드가 스택에 쌓인다.
7. introduce();
- 다시 introduce()
메서드를 호출했기 때문에, introduce()
로 돌아간다.
int sum(int value1, int value2) {
introduce();
int result = value1 + value2;
return result;
}
8. int sum(int value1, int value2) {
- 메서드를 돌아오면서 Stack 영역에서 introduce
가 없어진 걸 확인할 수 있다.
9. System.out.println(ret);
- ret
으로 저장해둔 값은 stack 에 쌓였고, sout
를 마지막으로 코드가 끝난 걸 확인 할 수 있다.
10. 출력문
11. Stack 과 Heap 정리
코드 | 변수 | 저장 위치 | 설명 |
---|---|---|---|
String name = "Steve"; |
name (참조 변수) |
Stack | "Steve" 를 가리키는 참조값 저장 |
"Steve" (문자열 객체) |
"Steve" |
Heap (String Constant Pool) | "Steve" 문자열이 저장됨 |
int age = 20; |
age |
Stack | 기본형(int )은 값 자체가 Stack에 저장됨 |
Person personA = new Person(name, age); |
personA (참조 변수) |
Stack | Person 객체를 가리키는 참조값 저장 |
(생성된 Person 객체) |
Person 객체 |
Heap | new 로 생성된 객체이므로 Heap에 저장 |
int value1 = 1; |
value1 |
Stack | 기본형(int )은 값 자체가 Stack에 저장됨 |
int value2 = 2; |
value2 |
Stack | 기본형(int )은 값 자체가 Stack에 저장됨 |
int ret = personA.sum(value1, value2); |
ret |
Stack | 기본형(int )은 값 자체가 Stack에 저장됨 |
3️⃣ 기본형과 참조형의 차이
✅ 기본형(Primitive Type)
int
,double
,boolean
,char
, ...- 값 자체를 Stack에 저장
- 빠른 접근 속도, 관리가 간단함 > 이러한 이유로 래퍼 변수보다 기본형 변수를 사용하는 방안으로 코드를 작성하는 것이 좋음.
- 기본형은 왜 Stack에 저장할까?
👉 기본형은 크기가 정해져 있고 작아서 빠르게 저장할 수 있기 때문
👉 참조형은 크기가 커질 수 있어서 동적 메모리 관리가 가능한 Heap을 사용
👉 자동 메모리 관리 때문 Stack 은 함수가 끝나면 자동으로 정리가 된다. (pop 연산)
✅ 참조형(Reference Type)
String
,Array
,Object
, ...- 실제 데이터는 Heap에 저장되고, Stack에는 Heap을 가리키는 주소(참조값) 저장
- 크기가 커질 수 있으므로 Heap에서 동적 메모리 할당
'코딩 공부 > Java' 카테고리의 다른 글
[Java] Chpater 2- 04) static - 클래스가 공유하는 공간 (0) | 2025.02.25 |
---|---|
[Java] Chpater 2- 03) 레퍼클래스 (기본형 참조형) (0) | 2025.02.25 |
[Java] Chpater 2- 01) 클래스와 객체 (1) | 2025.02.25 |
[Java]Chpater 1 - 10) 메서드 (0) | 2025.02.25 |
[Java]Chpater 1 - 09) 배열 (0) | 2025.02.25 |