F-lab Java 1์ฃผ์ฐจ / Phase 4 / Unit 4.1 ๋ณธ๊ฒฉ ํ์ต ์๋ฃ
9-์น์ ๋ง์คํฐ ํ๋กฌํํธ ํ์์ผ๋ก ๊น์ด ํํค์น๋ค.์ ์ ์ง์: Phase 1, 2 (OOP, ํด๋์ค/๊ฐ์ฒด)
๋ค์ Unit: 4.2 โ Pass by Value (์๋ฐ์ ์ง์ค)์ด Unit์ ์๋ฏธ: Phase 4 ์ ์์ โ ์ถ์์ ์ธ๊ณ์์ ๋ฌผ๋ฆฌ์ ์ธ๊ณ๋ก.
๋ฉด์ ์์ ๊ฑฐ์ 100% ์ถ์ ๋๋ ์์ญ. 4-5์ฃผ์ฐจ ๋์์ฑ/GC, 11-12์ฃผ์ฐจ JPA ์์์ฑ ์ปจํ ์คํธ์ ํ ๋.
ํฐ ๋์๊ด์ ์์ํด๋ณด์ธ์. ๋์๊ด์๋ ์ฌ๋ฌ ๊ณต๊ฐ ์ด ์์ต๋๋ค:
1์ธต โ ์นด์ดํฐ (PC Register):
2์ธต โ ์์ ์ฑ ์ (Stack):
3์ธต โ ์ฅ์ ๋ณด๊ด์ค (Heap):
์งํ โ ์นดํ๋ก๊ทธ์ค (Method Area):
โ JVM ๋ฉ๋ชจ๋ฆฌ๋ ๋น์ทํ ๊ตฌ์กฐ. ๊ฐ ๊ณต๊ฐ์ด ๋ค๋ฅธ ๋ชฉ์ .
๋น์ ์ด ํ์ฌ์์ ์ผํ๋ค๊ณ ์์ํด๋ณด์ธ์:
๊ณต์ ์บ๋น๋ (Heap):
๊ฐ์ธ ์ฑ ์ (Stack):
ํ์ฌ ๋งค๋ด์ผ (Method Area):
์ง๊ธ ํ๋ ์์ ํ์ (PC Register):
โ ์๋ฐ ํ๋ก๊ทธ๋จ์ด ์คํ๋ ๋ JVM ์์์ ์ ํํ ์ด๋ฐ ๊ณต๊ฐ๋ค์ด ๋ง๋ค์ด์ง๋๋ค.
"JVM์ ์๋ฐ ํ๋ก๊ทธ๋จ ์คํ์ ์ํด ๋ฉ๋ชจ๋ฆฌ๋ฅผ 5๊ฐ์ง ์์ญ์ผ๋ก ๋๋์ด ๊ด๋ฆฌํ๋ค."
5๊ฐ์ง ์์ญ์ ํต์ฌ ์ฐจ์ด:
| ์์ญ | ๊ณต์ ์ฌ๋ถ | ๋ณด๊ด ๋์ |
|---|---|---|
| Method Area | ๋ชจ๋ ์ค๋ ๋ ๊ณต์ | ํด๋์ค ์ ๋ณด, static |
| Heap | ๋ชจ๋ ์ค๋ ๋ ๊ณต์ | ๋ชจ๋ ๊ฐ์ฒด |
| Stack | ์ค๋ ๋๋ณ | ๋ฉ์๋ ํธ์ถ, ์ง์ญ๋ณ์ |
| PC Register | ์ค๋ ๋๋ณ | ํ์ฌ ๋ช ๋ น ์์น |
| Native Method Stack | ์ค๋ ๋๋ณ | ๋ค์ดํฐ๋ธ ๋ฉ์๋ |
ํ๋ก๊ทธ๋จ์ ๊ฒฐ๊ตญ ๋ฉ๋ชจ๋ฆฌ์์ ์คํ ๋ฉ๋๋ค. ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๊ฐ ์๋ชป๋๋ฉด:
C์์๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ด๋ฆฌ:
// C ์ฝ๋
int* arr = malloc(sizeof(int) * 100); // ๋ฉ๋ชจ๋ฆฌ ํ ๋น
// ... ์ฌ์ฉ ...
free(arr); // ๋ช
์์ ์ผ๋ก ํด์ โ
// ํด์ ์ ํ๋ฉด โ ๋ฉ๋ชจ๋ฆฌ ๋์
// ๋ ๋ฒ ํด์ ํ๋ฉด โ ์ถฉ๋
๋ฌธ์ :
Java(1995) ์ ํต์ฌ ์ฝ์:
"๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ JVM์ด ์์์"
์๋ฐ ๊ฐ๋ฐ์๋:
new ๋ก ๊ฐ์ฒด ์์ฑ๋ง์ด๋ฅผ ์ํด JVM์ ๋ช ํํ ๋ฉ๋ชจ๋ฆฌ ์์ญ ๊ตฌ๋ถ ์ด ํ์ํ์ต๋๋ค.
JVM Specification (1995~) ์์ ์ ์:
5๊ฐ์ง ์์ญ:
1. Method Area (๋ชจ๋ ์ค๋ ๋ ๊ณต์ )
2. Heap (๋ชจ๋ ์ค๋ ๋ ๊ณต์ )
3. Stack (์ค๋ ๋๋ณ)
4. PC Register (์ค๋ ๋๋ณ)
5. Native Method Stack (์ค๋ ๋๋ณ)
โ ์ด๊ฒ ๋ฉด์ ๋จ๊ณจ "JVM ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ".
์์ญ์ ๋๋๋ ์ด์ โญ :
"JVM ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ชจ๋ฅด๋ฉด ์๋ฐ๋ฅผ ์ง์ง ์ดํด ๋ชปํ ๊ฒ์ด๋ค."
Pass by Value (Unit 4.2), ๋์์ฑ (4์ฃผ์ฐจ), GC (5์ฃผ์ฐจ), JPA ์์์ฑ ์ปจํ ์คํธ (12์ฃผ์ฐจ) ๋ฑ โ ๋ชจ๋ ์๋ฐ์ ๊น์ ์ฃผ์ ๊ฐ ์ด ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ์์ ์๋ค.
๋ฉด์ ์์๋ ๊ฑฐ์ 100% ๋ฌป๋ ์์ญ. ๋ตํ ์ ์๋๋ ์๋๋๊ฐ ์๋์ด ์ฐจ๋ณํ ์ง์ .
๊น์ด ์ดํด ์์ด ์๋ฐ๋ฅผ ์ฐ๋ฉด ๋ค์ํ ๋ฌธ์ ์์ ๋งํ๋๋ค.
public class FareService {
private List<Fare> fares;
public int countFares() {
return fares.size(); // ๐ฅ NullPointerException
}
}
๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋ชจ๋ฅด๋ฉด:
๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ์๋ฉด:
fares ๋ ์ฐธ์กฐ ๋ณ์ (Stack ๋๋ Heap์ ๊ฐ์ฒด ์)public void process(List<Integer> list) {
list.add(100); // ํธ์ถ์์ list์๋ ์ํฅ?
}
List<Integer> myList = new ArrayList<>();
process(myList);
System.out.println(myList); // [100] โ ๏ธ ๋ณ๊ฒฝ๋จ!
๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋ชจ๋ฅด๋ฉด:
๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ์๋ฉด:
myList ๋ Stack์ ์ฐธ์กฐ ๋ณ์process(myList) โ ์ฐธ์กฐ์ ๊ฐ ์ด ๋ณต์ฌ๋์ด ์ ๋ฌlist ์ ์ธ๋ถ์ myList ๊ฐ ๊ฐ์ Heap ๊ฐ์ฒด ๊ฐ๋ฆฌํดโ Pass by Value์ ์ง์ค (Unit 4.2 ๋ฏธ๋ฆฌ๋ณด๊ธฐ).
List<byte[]> leaks = new ArrayList<>();
while (true) {
leaks.add(new byte<[1024 * 1024]); // 1MB์ฉ ์ถ๊ฐ
}
// ๐ฅ OutOfMemoryError: Java heap space
๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋ชจ๋ฅด๋ฉด:
๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ์๋ฉด:
leaks ๊ฐ GC ๋์ ์ ๋จ (์ฐธ์กฐ ์ด์์์)-Xmx ์ต์
์ผ๋ก Heap ์ฆ๊ฐ ๊ฐ๋ฅโ 5์ฃผ์ฐจ GC ํ์ต์ ํ ๋.
public void recursion() {
recursion(); // ๋ฌดํ ์ฌ๊ท
}
recursion(); // ๐ฅ StackOverflowError
๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋ชจ๋ฅด๋ฉด:
๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ์๋ฉด:
public class Counter {
private int count = 0;
public void increment() {
count++; // ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ๋ฌธ์
}
}
๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋ชจ๋ฅด๋ฉด:
๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ์๋ฉด:
count ๋ Heap ์ ๊ฐ์ฒด์ ์ํ ์ธ์คํด์ค ๋ณ์โ 4์ฃผ์ฐจ ๋์์ฑ ํ์ต์ ํ ๋.
"JVM ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ค๋ช ํด์ฃผ์ธ์"
๋๋ต ๋ชปํจ:
์ ๋ตํจ:
์ง๊ธ ํ์ต ์ ํ๋ฉด:
โ ์ด Unit์ด ํฅํ ๋ชจ๋ ์๋ฐ ํ์ต์ ํ ๋.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ JVM Runtime โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ Method Area โ โ Heap โ โ
โ โ (Class Info) โ โ (Objects) โ โ
โ โ โ โ โ โ
โ โ - ํด๋์ค ๋ฉํ โ โ - ๋ชจ๋ ๊ฐ์ฒด โ โ
โ โ - static ๋ณ์ โ โ - ์ธ์คํด์ค ๋ณ์โ โ
โ โ - Constant Poolโ โ - ๋ฐฐ์ด โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ (๋ชจ๋ ์ค๋ ๋ ๊ณต์ ) โ
โ โ
โ โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโโ โ
โ โ Thread 1 โ Thread 2 โ ... โ โ
โ โ โ โ โ โ
โ โ - PC Registerโ - PC Registerโ โ โ
โ โ - Stack โ - Stack โ โ โ
โ โ - Native โ - Native โ โ โ
โ โ Method Stk โ Method Stk โ โ โ
โ โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโโ โ
โ (์ค๋ ๋๋ณ ๋ถ๋ฆฌ) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
์ญํ : ํด๋์ค ์ ๋ณด ์ ์ฅ
์ ์ฅ ๋ด์ฉ:
ํน์ง:
์์:
public class Customer {
public static int count = 0; // Method Area์
private String name; // ๊ฐ์ฒด ๋ง๋ค (Heap์)
public void hello() { ... } // ๋ฉ์๋ ์ฝ๋ โ Method Area
}
์ญํ : ๋ชจ๋ ๊ฐ์ฒด ์ ์ฅ
์ ์ฅ ๋ด์ฉ:
new ๋ก ๋ง๋ ๋ชจ๋ ๊ฐ์ฒดํน์ง:
-Xmx, -Xms ์ต์
์ผ๋ก ํฌ๊ธฐ ์ค์ Heap ์ ๋ด๋ถ ๊ตฌ์กฐ (HotSpot JVM):
[Heap]
โโโ Young Generation
โ โโโ Eden
โ โโโ Survivor 0
โ โโโ Survivor 1
โโโ Old Generation
โ 5์ฃผ์ฐจ GC์์ ์์ธํ.
์์:
Customer c = new Customer();
// โ Heap์ Customer ์ธ์คํด์ค ์์ฑ
// c๋ Stack์ ์๋ ์ฐธ์กฐ ๋ณ์
์ญํ : ๋ฉ์๋ ํธ์ถ ์ ๋ณด, ์ง์ญ๋ณ์
์ ์ฅ ๋ด์ฉ:
ํน์ง:
Stack Frame ๊ตฌ์กฐ:
[Stack Frame]
- Local Variable Array (์ง์ญ๋ณ์)
- Operand Stack (๊ณ์ฐ์ฉ)
- Frame Data (๋ฆฌํด ์ฃผ์ ๋ฑ)
์์:
public void method1() { // Stack Frame 1
int x = 10; // Frame 1์ ์ง์ญ๋ณ์
method2(); // ์ Frame 2 ์ถ๊ฐ
int y = 20; // ๋ค์ Frame 1
}
public void method2() { // Stack Frame 2
int a = 100; // Frame 2์ ์ง์ญ๋ณ์
// method2 ์ข
๋ฃ โ Frame 2 ์ ๊ฑฐ
}
์ญํ : ํ์ฌ ์คํ ์ค์ธ ๋ช ๋ น์ ์ฃผ์
ํน์ง:
์์:
public void method() {
int x = 1; // PC: line 1
int y = 2; // PC: line 2
int z = x + y; // PC: line 3
}
โ ์ค๋ ๋ ์ ํ ์ ์ด๋๊น์ง ํ๋์ง ๊ธฐ์ตํ๋ ์ฉ๋.
์ญํ : ๋ค์ดํฐ๋ธ ๋ฉ์๋ (C/C++) ํธ์ถ ์ ๋ณด
์ ์ฅ ๋ด์ฉ:
ํน์ง:
์์:
public class System {
public static native long currentTimeMillis();
// โ ๋ค์ดํฐ๋ธ ๋ฉ์๋
}
System.currentTimeMillis();
// โ Java Stack์์ ํธ์ถ
// โ Native Method Stack์ผ๋ก ์ ํ
// โ C ์ฝ๋ ์คํ
โ ์ผ๋ฐ ๊ฐ๋ฐ์๊ฐ ์ง์ ๋ค๋ฃฐ ์ผ ์ ์.
| ์์ญ | ๊ณต์ ์ฌ๋ถ | ์ ์ฅ | ํฌ๊ธฐ | ์์ฑ ์์ |
|---|---|---|---|---|
| Method Area | ๋ชจ๋ ์ค๋ ๋ | ํด๋์ค ์ ๋ณด, static | ์ค | JVM ์์ |
| Heap | ๋ชจ๋ ์ค๋ ๋ | ๊ฐ์ฒด, ๋ฐฐ์ด | ๊ฐ์ฅ ํผ | JVM ์์ |
| Stack | ์ค๋ ๋๋ณ | ๋ฉ์๋ ํ๋ ์ | ์์ | ์ค๋ ๋ ์์ |
| PC Register | ์ค๋ ๋๋ณ | ํ์ฌ ๋ช ๋ น ์์น | ๋งค์ฐ ์์ | ์ค๋ ๋ ์์ |
| Native Method Stack | ์ค๋ ๋๋ณ | ๋ค์ดํฐ๋ธ ํธ์ถ | ์์ | ์ค๋ ๋ ์์ |
public class Customer {
private static int totalCount = 0; // โ static
private String name; // โก ์ธ์คํด์ค ๋ณ์
public void hello() {
int localVar = 10; // โข ์ง์ญ๋ณ์
Customer other = new Customer(); // โฃ ์ง์ญ ์ฐธ์กฐ ๋ณ์
}
}
์ ์ฅ ์์น:
totalCount (static) โ Method Areaname (์ธ์คํด์ค) โ Heap (๊ฐ์ฒด ์)localVar (์ง์ญ, ๊ธฐ๋ณธํ) โ Stackother (์ง์ญ ์ฐธ์กฐ) โ Stack (์ฐธ์กฐ), Heap (๊ฐ์ฒด)โ ๋ฉด์ ์์ ์์ฃผ ๋ฌป๋ ์ง๋ฌธ.
public class Hello {
public static void main(String[] args) {
Customer c = new Customer();
}
}
JVM ์์ ์:
1. ClassLoader๊ฐ .class ํ์ผ ์ฝ์
โ
2. ํด๋์ค ์ ๋ณด๋ฅผ Method Area์ ์ ์ฅ
- Customer ํด๋์ค ๋ฉํ๋ฐ์ดํฐ
- ๋ฉ์๋ ๋ฐ์ดํธ์ฝ๋
- static ๋ณ์ ์์ญ ํ ๋น
โ
3. main ๋ฉ์๋ ์คํ ์์
โ
4. main ๋ฉ์๋์ฉ Stack Frame ์์ฑ
- args ๋งค๊ฐ๋ณ์
- c ์ง์ญ๋ณ์ ์๋ฆฌ (์์ง ๋น์ด์์)
โ
5. new Customer() ์คํ
- Heap์ Customer ์ธ์คํด์ค ์์ฑ
- ์ธ์คํด์ค ๋ณ์ ์ด๊ธฐํ
โ
6. c์ ์ธ์คํด์ค ์ฐธ์กฐ ์ ์ฅ (Stack์ c ๋ณ์์)
๊ฒฐ๊ณผ ๋ฉ๋ชจ๋ฆฌ ์ํ:
[Method Area]
Customer ํด๋์ค ์ ๋ณด
[Heap]
Customer ์ธ์คํด์ค (์ธ์คํด์ค ๋ณ์๋ค)
โ
โ ์ฐธ์กฐ
[Stack โ main ์ค๋ ๋]
main Frame
- args
- c (์ฐธ์กฐ) โโโโโโ
public class Calculator {
public int add(int a, int b) {
int sum = a + b;
return sum;
}
}
Calculator calc = new Calculator();
int result = calc.add(3, 5);
Step 1 โ ํธ์ถ ์ง์ :
[Heap]
Calculator ์ธ์คํด์ค
โ
[Stack โ main]
main Frame
- calc (์ฐธ์กฐ)
- result (์์ง ๋ฏธํ ๋น)
Step 2 โ calc.add(3, 5) ํธ์ถ:
[Stack โ main]
main Frame
- calc
- result
โโโโโโโโโโโโโโโโ
โ add Frame โ โ ์ Frame ์ถ๊ฐ
โ - this (์ฐธ์กฐ)โ โ ์๋์ผ๋ก Calculator ์ธ์คํด์ค ์ฐธ์กฐ
โ - a = 3 โ โ ๋งค๊ฐ๋ณ์
โ - b = 5 โ
โ - sum = ? โ โ ์ง์ญ๋ณ์
โโโโโโโโโโโโโโโโ
Step 3 โ sum = a + b ์คํ:
add Frame
- this
- a = 3
- b = 5
- sum = 8 โ ๊ณ์ฐ ๊ฒฐ๊ณผ
Step 4 โ return:
[Stack โ main]
main Frame
- calc
- result = 8 โ ๋ฐํ๊ฐ ๋ฐ์
add Frame์ ์ ๊ฑฐ๋จ
โ Stack Frame์ด ๋ฉ์๋ ํธ์ถ์ ํต์ฌ.
public class Shared {
public int counter = 0; // ๊ณต์ ๋ฐ์ดํฐ
}
public class MyThread extends Thread {
private Shared shared;
private int localValue; // ์ค๋ ๋๋ณ ๋ฐ์ดํฐ
public void run() {
shared.counter++;
localValue = 100;
}
}
Shared shared = new Shared();
MyThread t1 = new MyThread();
t1.shared = shared;
t1.start();
MyThread t2 = new MyThread();
t2.shared = shared;
t2.start();
๋ฉ๋ชจ๋ฆฌ ์ํ:
[Method Area]
Shared ํด๋์ค ์ ๋ณด, MyThread ํด๋์ค ์ ๋ณด
[Heap] (๋ชจ๋ ์ค๋ ๋ ๊ณต์ )
Shared ์ธ์คํด์ค (counter)
โ โ
โ โ
[Stack t1] [Stack t2] (์ค๋ ๋๋ณ ๋ถ๋ฆฌ)
- shared - shared
์ฐธ์กฐ ์ฐธ์กฐ
- localValue - localValue
(๊ฐ์ ๋
๋ฆฝ) (๊ฐ์ ๋
๋ฆฝ)
ํต์ฌ:
shared.counter ๋ Heap ์ 1๊ฐ โ ๋ ์ค๋ ๋๊ฐ ๋์ ๋ณ๊ฒฝ ์ race conditionlocalValue ๋ ๊ฐ ์ค๋ ๋์ Stack ์ ๋ฐ๋ก โ ์์ โ 4์ฃผ์ฐจ ๋์์ฑ ํ์ต์ ํ ๋.
Java 7 ๊น์ง:
[JVM Heap]
โโโ Young Generation
โโโ Old Generation
โโโ PermGen (์๊ตฌ ์์ญ) โ Method Area์ ์ผ๋ถ
- ํด๋์ค ์ ๋ณด
- static ๋ณ์
- ์์ ํ
๋ฌธ์ :
OutOfMemoryError: PermGen space ์์ฃผ ๋ฐ์Java 8+:
[JVM Heap]
โโโ Young Generation
โโโ Old Generation
[Native Memory]
โโโ Metaspace โ Method Area
- ๋์ ํฌ๊ธฐ ์กฐ์ (OS ๋ฉ๋ชจ๋ฆฌ ํ๋๊น์ง)
- ๋ ์์ ์
ํจ๊ณผ:
OutOfMemoryError: PermGen space ์ฌ๋ผ์งOutOfMemoryError: Metaspace ๊ฐ๋ฅ (๋๋ฌธ ์ผ)โ ๋ฉด์ ๋น์ถ ์ง๋ฌธ: "Java 8 ์ดํ ๋ฉ๋ชจ๋ฆฌ ๋ณํ?"
๋ฌธ์์ด์ ํน๋ณ ์ทจ๊ธ:
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
s1 == s2; // true (๊ฐ์ String Pool ์ฐธ์กฐ)
s1 == s3; // false (s3๋ Heap์ ์ ๊ฐ์ฒด)
s1.equals(s3); // true (๊ฐ ๋น๊ต)
๋ฉ๋ชจ๋ฆฌ ์ํ:
[Method Area / Heap์ ํน๋ณ ์์ญ]
String Constant Pool
"hello" โ 1๊ฐ๋ง
โ โ
โ โ
[Heap]
์ String ๊ฐ์ฒด (s3๊ฐ ๊ฐ๋ฆฌํด)
โ
โ
[Stack]
s1 โโโโ
s2 โโโโ
s3 โโโโ (์ ๊ฐ์ฒด ๊ฐ๋ฆฌํด)
โ 6์ฃผ์ฐจ String ํ์ต ์ผ๋ก ์ฐ๊ฒฐ.
public class FareSystem {
// Method Area์ ์ ์ฅ
private static int totalFareCount = 0;
private static final String VERSION = "1.0";
// ์ธ์คํด์ค ๋ณ์ โ ๊ฐ์ฒด์ ํจ๊ป Heap์
private Long id;
private int amount;
private FareStatus status;
// ๋ฉ์๋ ์ฝ๋ โ Method Area์
public void changeAmount(int newAmount) {
// ๋งค๊ฐ๋ณ์ newAmount, ์ง์ญ๋ณ์ โ Stack
int oldAmount = this.amount; // ์ง์ญ๋ณ์
if (newAmount < 0) {
throw new IllegalArgumentException();
}
this.amount = newAmount; // Heap์ ์ธ์คํด์ค ๋ณ์ ๋ณ๊ฒฝ
totalFareCount++; // Method Area์ static ๋ณ๊ฒฝ
}
}
๋ฉ๋ชจ๋ฆฌ ์ถ์ :
totalFareCount โ Method AreaVERSION โ Method Area + String Poolid, amount, status โ Heap (๊ฐ ์ธ์คํด์ค๋ง๋ค)changeAmount ๋ฉ์๋ ์ฝ๋ โ Method AreanewAmount, oldAmount โ Stack (ํธ์ถ ์)public class FareDemo {
public static void main(String[] args) {
// Step 1: Customer ์ธ์คํด์ค ์์ฑ
Customer alice = new Customer("Alice");
// alice โ Stack
// Customer ์ธ์คํด์ค โ Heap
// Step 2: Fare ์ธ์คํด์ค ์์ฑ
Fare fare = new Fare(50000, alice);
// fare โ Stack
// Fare ์ธ์คํด์ค โ Heap (customer ํ๋๋ alice ์ฐธ์กฐ)
// Step 3: ๊ฐ์ alice ์ฐธ์กฐ
Fare fare2 = new Fare(80000, alice);
// alice ๊ฐ์ฒด๋ Heap์ 1๊ฐ, ๋ Fare๊ฐ ๊ณต์
// Step 4: alice ๋ณ๊ฒฝ
alice.setName("Alice Smith");
// โ Heap์ Customer ๊ฐ์ฒด ๋ณ๊ฒฝ
// โ fare.customer.getName() == "Alice Smith"
// โ fare2.customer.getName() == "Alice Smith"
}
}
๋ฉ๋ชจ๋ฆฌ ๊ทธ๋ฆผ:
[Heap]
Customer ("Alice Smith") โ 1๊ฐ
โ โ
โ โ
Fare(50000) Fare(80000)
โ โ
โ โ
[Stack โ main]
alice โโโโโโโโโโโโโโ
fare โโโโโโโโโโโโโโโค
fare2 โโโโโโโโโโโโโโ
public class StackDemo {
public static int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1); // ์ฌ๊ท
}
public static void main(String[] args) {
System.out.println(factorial(10)); // OK
System.out.println(factorial(100000)); // ๐ฅ StackOverflowError
}
}
์ StackOverflow?:
ํด๊ฒฐ:
// ๋ฐ๋ณต๋ฌธ์ผ๋ก
public static int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; i++) {
result *= i;
}
return result;
}
โ Stack์ ๊ฑฐ์ ์ ์.
public class HeapDemo {
public static void main(String[] args) {
List<byte[]> list = new ArrayList<>();
for (int i = 0; i < Integer.MAX_VALUE; i++) {
list.add(new byte[1024 * 1024]); // 1MB์ฉ ์ถ๊ฐ
// ๐ฅ OutOfMemoryError: Java heap space
}
}
}
ํด๊ฒฐ:
# JVM ์ต์
์ผ๋ก Heap ํฌ๊ธฐ ์ฆ๊ฐ
java -Xmx4g HeapDemo # 4GB๋ก ์ฆ๊ฐ
๊ทผ๋ณธ ํด๊ฒฐ: ๋ถํ์ํ ์ฐธ์กฐ ์ ๊ฑฐ (5์ฃผ์ฐจ GC).
public class CounterTest {
private int count = 0; // Heap์ ์ธ์คํด์ค ๋ณ์
public void increment() {
count++; // ๋ฉํฐ์ค๋ ๋์ ์ํ
}
public static void main(String[] args) throws InterruptedException {
CounterTest counter = new CounterTest();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) counter.increment();
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) counter.increment();
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.count); // 20000? โ ๋ณดํต ์ ๊ฒ ๋์ด
}
}
์ ์ ๊ฒ?:
count ๋ Heap ์ ๊ฐ์ฒด์ ์ํจ (๊ณต์ )count++ ๋ read โ modify โ write 3 ๋จ๊ณํด๊ฒฐ:
private AtomicInteger count = new AtomicInteger(0);
// ๋๋ synchronized
โ 4์ฃผ์ฐจ ๋์์ฑ์์ ๋ณธ๊ฒฉ.
Q: "JVM ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ?"
A: "Stack๊ณผ Heap์ด์"
โ 5๊ฐ์ง ์์ญ ์ค 2๊ฐ๋ง. ๋ฉด์ ์์ ๊น์ด ๋ถ์กฑ ๋ ธ์ถ.
์ฌ๋ฐ๋ฅธ ๋ต: Method Area, Heap, Stack, PC Register, Native Method Stack โ 5๊ฐ์ง + ๊ฐ๊ฐ์ ์ญํ .
Q: "static ๋ณ์๋ ์ด๋์?"
A: "Heap์ด์" โ
์ ๋ต: Method Area (Java 8+ Metaspace).
์ด์ :
Customer.totalCount; // ์ธ์คํด์ค ์์ด ์ ๊ทผ
// โ Method Area์ ์์ด์ผ ๊ฐ๋ฅ
Q: "๊ฐ์ฒด๋ ์ด๋์ ์ ์ฅ?"
A: "Heap" โ (ํ๋ฆฐ ๊ฑด ์๋์ง๋ง ๋ถ์ ํ)
๋ณด๋ค ์ ํํ ๋ต:
Q: "Java 8 ์ดํ PermGen์?"
A: "PermGen์ด ๋ ์ปค์ก์ด์" โ
์ ๋ต: PermGen์ด ์ฌ๋ผ์ง๊ณ Metaspace๋ก ๊ต์ฒด.
public void recursion(int depth) {
// 1๋ง ๋ฒ ์ฌ๊ท
if (depth < 10000) recursion(depth + 1);
}
recursion(0); // ๐ฅ StackOverflowError ๊ฐ๋ฅ
โ Stack์ ์๋ฐฑ KB ~ ์ MB. Heap (์ GB) ์ ๋งค์ฐ ๋ค๋ฆ.
Q: "์ง์ญ๋ณ์๊ฐ GC ๋์?"
A: "๋ค" โ
์ ๋ต: ์ง์ญ๋ณ์๋ ๋ฉ์๋ ์ข ๋ฃ ์ ์๋ ์ ๊ฑฐ (Stack Frame ์ ๊ฑฐ). GC ๋์ ์๋.
public void method() {
int x = 10; // Stack ์
String s = "hello"; // s๋ Stack์ ์ฐธ์กฐ, "hello"๋ ๋ณ๋
}
// ๋ฉ์๋ ์ข
๋ฃ โ x, s ์๋ ์ ๊ฑฐ
GC ๋์์ Heap ์ ๊ฐ์ฒด ๋ง.
ํํ ์คํด:
java -Xmx4g # Heap๋ง ์ค์ ?
์ ๋ต: ๋ค์ํ ์์ญ ์ค์ ๊ฐ๋ฅ.
JVM ์ต์ โญ :
-Xms<size> # Heap ์ด๊ธฐ ํฌ๊ธฐ
-Xmx<size> # Heap ์ต๋ ํฌ๊ธฐ
-Xss<size> # Stack ํฌ๊ธฐ (์ค๋ ๋๋ณ)
-XX:MetaspaceSize=<size> # Metaspace ์ด๊ธฐ
-XX:MaxMetaspaceSize=<size> # Metaspace ์ต๋
-XX:+HeapDumpOnOutOfMemoryError # OOM ์ ๋คํ
[Unit 4.1: JVM ๋ฐํ์ ๋ฐ์ดํฐ ์์ญ] โ ์ง๊ธ ์ฌ๊ธฐ
โ
[Unit 4.2: Pass by Value (์๋ฐ์ ์ง์ค)]
๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ์์์ ๊ฐ/์ฐธ์กฐ ์ ๋ฌ ์ดํด
Phase 4์ ์๋ฏธ:
์ด์ ํ์ต ๋ค์ ๋ณด๊ธฐ:
| Phase 2 ํ์ต | ๋ฉ๋ชจ๋ฆฌ ๊ด์ |
|---|---|
| Unit 2.1 (๋ฉ์๋) | Stack Frame |
| Unit 2.3 (์์) | Heap์ ๊ฐ์ฒด์ ๋ถ๋ชจ+์์ ํ๋ ํจ๊ป |
| Unit 2.4 (๋คํ์ฑ) | VMT๊ฐ Method Area์ |
| Unit 2.6 (Inner) | Outer ์ธ์คํด์ค ์ฐธ์กฐ๊ฐ Heap์ |
โ ์ด์ ํ์ต์ด ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ์์์ ์ดํด๋จ.
Phase 5 (GC):
Phase 6 (String, ์ปฌ๋ ์ ):
Phase 7 (I/O):
4์ฃผ์ฐจ (๋์์ฑ):
5์ฃผ์ฐจ (Spring):
11-12์ฃผ์ฐจ (JPA):
17์ฃผ์ฐจ (MSA):
โ ๋ชจ๋ ์๋ฐ ํ์ต์ ํ ๋.
[Java 1.0 ~ 1.4]
- ๋จ์ ๋ฉ๋ชจ๋ฆฌ ๋ชจ๋ธ
- Stop-the-world GC
[Java 5]
- JVM Memory Model ์ ๋ฆฝ
- volatile, synchronized ์๋ฏธ ๋ช
ํํ
[Java 7]
- G1 GC ๋์
(Heap ์์ญํ)
[Java 8] โญ
- PermGen โ Metaspace
- ๋๋ค, Stream
[Java 11]
- ZGC (๋์ฉ๋ Heap)
[Java 21+]
- Generational ZGC
- Project Loom (๊ฐ์ ์ค๋ ๋)
โ ๋ฉ๋ชจ๋ฆฌ ๋ชจ๋ธ์ ๋์์ด ์งํ.
| ์ง๋ฌธ | ์ด Unit์์์ ๋ต |
|---|---|
| "JVM ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ?" | 5๊ฐ์ง ์์ญ + ๊ฐ ์ญํ |
| "static ๋ณ์๋ ์ด๋?" | Method Area |
| "Stack๊ณผ Heap ์ฐจ์ด?" | ์ค๋ ๋๋ณ/๊ณต์ , ์์/ํผ, ์๋ ์ ๋ฆฌ/GC |
| "Java 8 ๋ฉ๋ชจ๋ฆฌ ๋ณํ?" | PermGen โ Metaspace |
| "OutOfMemoryError ์ข ๋ฅ?" | Heap, Metaspace, Stack |
| "Stack Overflow vs OOM?" | Stack vs Heap |
1๏ธโฃ JVM ๋ฉ๋ชจ๋ฆฌ๋ 5๊ฐ์ง ์์ญ โ Method Area, Heap, Stack, PC Register, Native Method Stack.
๊ณต์ ์์ญ (Method Area, Heap) ๊ณผ ์ค๋ ๋๋ณ ์์ญ (Stack, PC Register, Native Method Stack) ์ผ๋ก ๋๋๋ค. Method Area ๋ ํด๋์ค ์ ๋ณด์ static, Heap ์ ๋ชจ๋ ๊ฐ์ฒด, Stack ์ ๋ฉ์๋ ํธ์ถ๊ณผ ์ง์ญ๋ณ์. ์ด ๊ตฌ๋ถ์ด ๋์์ฑ/GC/์ฑ๋ฅ ์ต์ ํ์ ํ ๋.
2๏ธโฃ ๋ณ์๋ ์ข ๋ฅ์ ๋ฐ๋ผ ์ ์ฅ ์์น๊ฐ ๋ค๋ฅด๋ค.
static ๋ณ์ โ Method Area, ์ธ์คํด์ค ๋ณ์ โ Heap (๊ฐ์ฒด ์), ์ง์ญ๋ณ์ (๊ธฐ๋ณธํ) โ Stack, ์ง์ญ ์ฐธ์กฐ ๋ณ์ โ Stack (์ฐธ์กฐ), Heap (๊ฐ์ฒด). ๋ฉด์ ์์ ์์ฃผ ๋ฌป๋ ์์ญ. Pass by Value (Unit 4.2) ์ ํต์ฌ ํ ๋.
3๏ธโฃ Java 8 ์ดํ PermGen์ด Metaspace ๋ก ๊ต์ฒด๋๋ค.
Java 7 ๊น์ง์ PermGen ์ Heap ์์ ๊ณ ์ ํฌ๊ธฐ๋ก ์์ด
OutOfMemoryError: PermGen space๊ฐ ์ฆ์๋ค. Java 8+ ์ Metaspace ๋ Native Memory ์์ ๋์ ํฌ๊ธฐ, ๋ ์์ ์ . JVM ์ต์ -Xms/-Xmx(Heap),-Xss(Stack),-XX:MaxMetaspaceSize(Metaspace) ๋ก ๊ฐ ์์ญ ํต์ ๊ฐ๋ฅ.
Q1: Member m = new Member() ์์ m์ ์ด๋์, ๊ฐ์ฒด ๋ณธ์ฒด๋ ์ด๋์ ์ ์ฅ๋๋๊ฐ?
ํ ์ค ๋ต: m ์ Stack (๋๋ Heap, ์์น์ ๋ฐ๋ผ), ๊ฐ์ฒด ๋ณธ์ฒด๋ Heap.
์์ธ ์ค๋ช :
์ ์ฝ๋๋ฅผ ๋ถํด:
Member m = new Member();
// โ โ
// ๋ณ์ ๊ฐ์ฒด
m ์ ์ ์ฅ ์์น โ ์ปจํ
์คํธ์ ๋ฐ๋ผ:
// Case 1: ๋ฉ์๋ ์์ ์ง์ญ๋ณ์
public void method() {
Member m = new Member();
// m์ Stack์ method Frame ์ โ Stack
}
// Case 2: ํด๋์ค์ ์ธ์คํด์ค ๋ณ์
public class Service {
private Member m; // m์ Service ์ธ์คํด์ค ์ โ Heap
}
// Case 3: static ๋ณ์
public class Service {
private static Member m; // m์ Method Area
}
๊ฐ์ฒด ๋ณธ์ฒด (new Member() ๋ก ์์ฑ๋ ๊ฒ):
new ํค์๋ = "Heap์ ๊ฐ์ฒด ์์ฑ"๋ฉ๋ชจ๋ฆฌ ๊ทธ๋ฆผ (Case 1):
[Stack โ ๋ฉ์๋ Frame]
m (์ฐธ์กฐ) โโโโโโ
โ
[Heap] โ
Member ์ธ์คํด์ค โโโ
- ์ธ์คํด์ค ๋ณ์๋ค
m == ๊ฐ์ฒด ๋ณธ์ฒด ๊ฐ ์๋:
m ์ ์ฐธ์กฐ ๋ณ์ (๊ฐ์ฒด์ ์ฃผ์๋ฅผ ๋ด์)Q2: static ๋ณ์์ ์ธ์คํด์ค ๋ณ์์ ์ ์ฅ ์์น ์ฐจ์ด๋?
ํ ์ค ๋ต: static ๋ณ์ โ Method Area, ์ธ์คํด์ค ๋ณ์ โ Heap (๊ฐ์ฒด ์).
์์ธ ์ค๋ช :
public class Customer {
private static int totalCount = 0; // static
private String name; // ์ธ์คํด์ค
public Customer(String name) {
this.name = name;
totalCount++;
}
}
Customer c1 = new Customer("Alice");
Customer c2 = new Customer("Bob");
๋ฉ๋ชจ๋ฆฌ ์ํ:
[Method Area]
Customer ํด๋์ค ์ ๋ณด
- totalCount: 2 โ 1๊ฐ๋ง ์กด์ฌ โญ
[Heap]
c1 ์ธ์คํด์ค c2 ์ธ์คํด์ค
- name: "Alice" - name: "Bob"
(totalCount๋ ์ฌ๊ธฐ ์์)
โ โ
โ โ
[Stack]
c1 โโโ โ
c2 โโโโโโโโโโโโโโโโโโโโ
ํต์ฌ ์ฐจ์ด โญ :
| static ๋ณ์ | ์ธ์คํด์ค ๋ณ์ | |
|---|---|---|
| ๊ฐ์ | ํด๋์ค๋น 1๊ฐ | ์ธ์คํด์ค๋ง๋ค 1๊ฐ |
| ์ ์ฅ ์์น | Method Area | Heap (๊ฐ์ฒด ์) |
| ์๋ช | ํด๋์ค ๋ก๋ ~ JVM ์ข ๋ฃ | ๊ฐ์ฒด ์์ฑ ~ GC |
| ์ ๊ทผ | ํด๋์ค๋ช .๋ณ์ | ์ธ์คํด์ค.๋ณ์ |
| GC | ์ผ๋ฐ์ ์ผ๋ก X | ๊ฐ์ฒด GC ์ ํจ๊ป |
์ ์ด๋ ๊ฒ ๋ค๋ฅธ๊ฐ?:
์ค์ฉ์ ํจ์:
public class Counter {
private static int total = 0; // ๋ชจ๋ ์ธ์คํด์ค๊ฐ ๊ณต์
private int myCount = 0; // ๊ฐ ์ธ์คํด์ค๋ง์ ๊ฐ
public void count() {
total++;
myCount++;
}
}
Counter c1 = new Counter();
Counter c2 = new Counter();
c1.count(); c1.count(); // total = 2, c1.myCount = 2
c2.count(); // total = 3, c2.myCount = 1
๊ฒฐ๊ณผ:
total ์ ๊ณต์ โ 3myCount ๋ ๊ฐ์ โ c1: 2, c2: 1โ static ์ ๋ณธ์ง์ด ๋ฉ๋ชจ๋ฆฌ ์์น์์ ๋๋ฌ๋จ.
๋ฉํฐ์ค๋ ๋ ์ ์ํ โ ๏ธ :