๐ŸŽฏ1์ฃผ์ฐจ Unit 4.1 โ€” JVM ๋Ÿฐํƒ€์ž„ ๋ฐ์ดํ„ฐ ์˜์—ญ

Psjยท7์ผ ์ „

F-lab

๋ชฉ๋ก ๋ณด๊ธฐ
35/52

๐ŸŽฏ Unit 4.1 โ€” JVM ๋Ÿฐํƒ€์ž„ ๋ฐ์ดํ„ฐ ์˜์—ญ โ˜…โ˜…โ˜…

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. ์„ธ์ƒ ์† ๋น„์œ 

JVM ๋ฉ”๋ชจ๋ฆฌ = "์ž˜ ์ •๋ฆฌ๋œ ๋„์„œ๊ด€"

ํฐ ๋„์„œ๊ด€์„ ์ƒ์ƒํ•ด๋ณด์„ธ์š”. ๋„์„œ๊ด€์—๋Š” ์—ฌ๋Ÿฌ ๊ณต๊ฐ„ ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

1์ธต โ€” ์นด์šดํ„ฐ (PC Register):

  • ์‚ฌ์„œ๊ฐ€ ์ง€๊ธˆ ์–ด๋–ค ์ฑ…์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ‘œ์‹œ
  • ๋งค ์ˆœ๊ฐ„ ํ•œ ๊ฐ€์ง€ ์ผ๋งŒ

2์ธต โ€” ์ž‘์—… ์ฑ…์ƒ (Stack):

  • ์‚ฌ์„œ๊ฐ€ ์ž‘์—… ์ค‘์ธ ๋ฉ”๋ชจ, ์ž„์‹œ ์ž๋ฃŒ ๋ณด๊ด€
  • ์ž‘์—… ๋๋‚˜๋ฉด ์ •๋ฆฌ
  • ๋‹ค๋ฅธ ์‚ฌ์„œ๋Š” ๋‹ค๋ฅธ ์ฑ…์ƒ

3์ธต โ€” ์žฅ์„œ ๋ณด๊ด€์‹ค (Heap):

  • ๋ชจ๋“  ์ฑ…์˜ ๋ณธ์ฒด ์ €์žฅ
  • ๊ฐ€์žฅ ํฐ ๊ณต๊ฐ„
  • ์—ฌ๋Ÿฌ ์‚ฌ์„œ๊ฐ€ ๊ณต์œ 

์ง€ํ•˜ โ€” ์นดํƒˆ๋กœ๊ทธ์‹ค (Method Area):

  • ์ฑ…์˜ ๋ชฉ๋ก, ๋ถ„๋ฅ˜ ์ •๋ณด, ์ €์ž ์ •๋ณด
  • ๋ชจ๋“  ์‚ฌ์„œ๊ฐ€ ์ฐธ์กฐ
  • ํ•œ ๋ฒˆ ๋งŒ๋“ค๋ฉด ๊ฑฐ์˜ ์•ˆ ๋ฐ”๋€œ

โ†’ JVM ๋ฉ”๋ชจ๋ฆฌ๋„ ๋น„์Šทํ•œ ๊ตฌ์กฐ. ๊ฐ ๊ณต๊ฐ„์ด ๋‹ค๋ฅธ ๋ชฉ์ .


๋” ์ง๊ด€์ ์ธ ๋น„์œ  โ€” "์‚ฌ๋ฌด์‹ค"

๋‹น์‹ ์ด ํšŒ์‚ฌ์—์„œ ์ผํ•œ๋‹ค๊ณ  ์ƒ์ƒํ•ด๋ณด์„ธ์š”:

๊ณต์œ  ์บ๋น„๋‹› (Heap):

  • ๋ชจ๋“  ์ง์›์ด ์‚ฌ์šฉํ•˜๋Š” ๊ณต๋™ ์ž๋ฃŒ
  • ๋ณด๊ณ ์„œ ์›๋ณธ, ํšŒ์‚ฌ ๋ฌธ์„œ๋“ค
  • ๋ˆ„๊ฐ€ ์‚ฌ์šฉ ์ค‘์ธ์ง€ ์ถ”์  ํ•„์š” (GC)

๊ฐœ์ธ ์ฑ…์ƒ (Stack):

  • ๋‹น์‹ ๋งŒ์˜ ์ž‘์—… ๊ณต๊ฐ„
  • ์ž„์‹œ ๋ฉ”๋ชจ, ๊ณ„์‚ฐ๊ธฐ, ์—ฐํ•„
  • ๋‹ค๋ฅธ ์ง์›๊ณผ ๊ณต์œ  X
  • ์ผ์ด ๋๋‚˜๋ฉด ์ •๋ฆฌ

ํšŒ์‚ฌ ๋งค๋‰ด์–ผ (Method Area):

  • ํšŒ์‚ฌ ๊ทœ์ •, ์ง๋ฌด ์„ค๋ช…์„œ
  • ๋ชจ๋“  ์ง์›์ด ์ฐธ์กฐ
  • ์ž˜ ์•ˆ ๋ฐ”๋€œ

์ง€๊ธˆ ํ•˜๋Š” ์ž‘์—… ํ‘œ์‹œ (PC Register):

  • ์ฑ…์ƒ ์œ„ "ํ˜„์žฌ ์ž‘์—…: ๋ณด๊ณ ์„œ ์ž‘์„ฑ" ํ‘œ์ง€

โ†’ ์ž๋ฐ” ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋  ๋•Œ JVM ์•ˆ์—์„œ ์ •ํ™•ํžˆ ์ด๋Ÿฐ ๊ณต๊ฐ„๋“ค์ด ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค.


ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

"JVM์€ ์ž๋ฐ” ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰์„ ์œ„ํ•ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ 5๊ฐ€์ง€ ์˜์—ญ์œผ๋กœ ๋‚˜๋ˆ„์–ด ๊ด€๋ฆฌํ•œ๋‹ค."

5๊ฐ€์ง€ ์˜์—ญ์˜ ํ•ต์‹ฌ ์ฐจ์ด:

์˜์—ญ๊ณต์œ  ์—ฌ๋ถ€๋ณด๊ด€ ๋Œ€์ƒ
Method Area๋ชจ๋“  ์Šค๋ ˆ๋“œ ๊ณต์œ ํด๋ž˜์Šค ์ •๋ณด, static
Heap๋ชจ๋“  ์Šค๋ ˆ๋“œ ๊ณต์œ ๋ชจ๋“  ๊ฐ์ฒด
Stack์Šค๋ ˆ๋“œ๋ณ„๋ฉ”์„œ๋“œ ํ˜ธ์ถœ, ์ง€์—ญ๋ณ€์ˆ˜
PC Register์Šค๋ ˆ๋“œ๋ณ„ํ˜„์žฌ ๋ช…๋ น ์œ„์น˜
Native Method Stack์Šค๋ ˆ๋“œ๋ณ„๋„ค์ดํ‹ฐ๋ธŒ ๋ฉ”์„œ๋“œ

๐Ÿ”ฅ 2. ํƒ„์ƒ ๋ฐฐ๊ฒฝ

"๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ž˜ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒŒ ์™œ ์ค‘์š”ํ•œ๊ฐ€?"

ํ”„๋กœ๊ทธ๋žจ์€ ๊ฒฐ๊ตญ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์‹คํ–‰ ๋ฉ๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๊ฐ€ ์ž˜๋ชป๋˜๋ฉด:

  • ํ”„๋กœ๊ทธ๋žจ ์ถฉ๋Œ (Crash)
  • ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ (Memory Leak)
  • ๋ณด์•ˆ ์ทจ์•ฝ์ 

C/C++ ์˜ ์‹œ๋Œ€ โ€” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๊ด€๋ฆฌ

C์—์„œ๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๊ด€๋ฆฌ:

// C ์ฝ”๋“œ
int* arr = malloc(sizeof(int) * 100);  // ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น
// ... ์‚ฌ์šฉ ...
free(arr);  // ๋ช…์‹œ์ ์œผ๋กœ ํ•ด์ œ โ—
// ํ•ด์ œ ์•ˆ ํ•˜๋ฉด โ†’ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜
// ๋‘ ๋ฒˆ ํ•ด์ œํ•˜๋ฉด โ†’ ์ถฉ๋Œ

๋ฌธ์ œ:

  • ๊ฐœ๋ฐœ์ž ์‹ค์ˆ˜๋กœ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜, ๋Œ•๊ธ€๋ง ํฌ์ธํ„ฐ ๋“ฑ
  • ๋ณด์•ˆ ์ทจ์•ฝ์  (Buffer Overflow)
  • ๋””๋ฒ„๊น… ์ง€์˜ฅ

Java ์˜ ๋“ฑ์žฅ โ€” "๋ฉ”๋ชจ๋ฆฌ ์ž๋™ ๊ด€๋ฆฌ"

Java(1995) ์˜ ํ•ต์‹ฌ ์•ฝ์†:

"๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋Š” JVM์ด ์•Œ์•„์„œ"

์ž๋ฐ” ๊ฐœ๋ฐœ์ž๋Š”:

  • new ๋กœ ๊ฐ์ฒด ์ƒ์„ฑ๋งŒ
  • ํ•ด์ œ๋Š” GC๊ฐ€ ์ž๋™
  • ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์œ„ํ—˜ โ†“
  • ๋ณด์•ˆ โ†‘

์ด๋ฅผ ์œ„ํ•ด JVM์€ ๋ช…ํ™•ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ ๊ตฌ๋ถ„ ์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.


JVM ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋ธ์˜ ํ‘œ์ค€ํ™”

JVM Specification (1995~) ์—์„œ ์ •์˜:

  • ๋ชจ๋“  ์ž๋ฐ” ๊ตฌํ˜„์ฒด๊ฐ€ ๋”ฐ๋ผ์•ผ ํ•  ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ ํ‘œ์ค€
  • HotSpot, OpenJDK, GraalVM ๋“ฑ ๋ชจ๋‘ ์ด ๋ชจ๋ธ ๋”ฐ๋ฆ„

5๊ฐ€์ง€ ์˜์—ญ:
1. Method Area (๋ชจ๋“  ์Šค๋ ˆ๋“œ ๊ณต์œ )
2. Heap (๋ชจ๋“  ์Šค๋ ˆ๋“œ ๊ณต์œ )
3. Stack (์Šค๋ ˆ๋“œ๋ณ„)
4. PC Register (์Šค๋ ˆ๋“œ๋ณ„)
5. Native Method Stack (์Šค๋ ˆ๋“œ๋ณ„)

โ†’ ์ด๊ฒŒ ๋ฉด์ ‘ ๋‹จ๊ณจ "JVM ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ".


์™œ ์˜์—ญ์„ ๋‚˜๋ˆ„๋‚˜?

์˜์—ญ์„ ๋‚˜๋ˆ„๋Š” ์ด์œ  โญ :

1. ์ƒ๋ช…์ฃผ๊ธฐ ๊ด€๋ฆฌ

  • ์–ด๋–ค ๋ฐ์ดํ„ฐ๋Š” ์˜ค๋ž˜ ์‚ด๊ณ  (ํด๋ž˜์Šค ์ •๋ณด, ์ผ๋ถ€ ๊ฐ์ฒด)
  • ์–ด๋–ค ๋ฐ์ดํ„ฐ๋Š” ์งง๊ฒŒ ์‚ด๊ณ  (์ง€์—ญ๋ณ€์ˆ˜, ์ž„์‹œ ๊ฐ์ฒด)
  • โ†’ ์˜์—ญ๋งˆ๋‹ค ๋‹ค๋ฅธ GC ์ „๋žต

2. ๋™์‹œ์„ฑ

  • ์Šค๋ ˆ๋“œ๋ณ„ ์˜์—ญ (Stack, PC Register) โ†’ ๋™๊ธฐํ™” ๋ถˆํ•„์š”
  • ๊ณต์œ  ์˜์—ญ (Heap, Method Area) โ†’ ๋™๊ธฐํ™” ํ•„์š”

3. ์„ฑ๋Šฅ ์ตœ์ ํ™”

  • Stack์€ ๋งค์šฐ ๋น ๋ฆ„ (LIFO, ๋‹จ์ˆœ)
  • Heap์€ GC ํ•„์š”ํ•˜์ง€๋งŒ ์œ ์—ฐ

4. ๋ณด์•ˆ

  • ์˜์—ญ ๋ถ„๋ฆฌ๋กœ ๋ฉ”๋ชจ๋ฆฌ ์นจ์ž… ๋ฐฉ์–ด

ํ•ต์‹ฌ ํ†ต์ฐฐ

"JVM ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ชจ๋ฅด๋ฉด ์ž๋ฐ”๋ฅผ ์ง„์งœ ์ดํ•ด ๋ชปํ•œ ๊ฒƒ์ด๋‹ค."

Pass by Value (Unit 4.2), ๋™์‹œ์„ฑ (4์ฃผ์ฐจ), GC (5์ฃผ์ฐจ), JPA ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ (12์ฃผ์ฐจ) ๋“ฑ โ€” ๋ชจ๋“  ์ž๋ฐ”์˜ ๊นŠ์€ ์ฃผ์ œ๊ฐ€ ์ด ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์œ„์— ์žˆ๋‹ค.

๋ฉด์ ‘์—์„œ๋„ ๊ฑฐ์˜ 100% ๋ฌป๋Š” ์˜์—ญ. ๋‹ตํ•  ์ˆ˜ ์žˆ๋А๋ƒ ์—†๋А๋ƒ๊ฐ€ ์‹œ๋‹ˆ์–ด ์ฐจ๋ณ„ํ™” ์ง€์ .


๐Ÿ’ฃ 3. ์—†์œผ๋ฉด ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ

"๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ชจ๋ฅด๊ณ  ์ž๋ฐ”๋ฅผ ์“ฐ๋ฉด?"

๊นŠ์ด ์ดํ•ด ์—†์ด ์ž๋ฐ”๋ฅผ ์“ฐ๋ฉด ๋‹ค์–‘ํ•œ ๋ฌธ์ œ์—์„œ ๋ง‰ํž™๋‹ˆ๋‹ค.


์‹œ๋‚˜๋ฆฌ์˜ค 1: NullPointerException ์˜ ์ง„์งœ ์›์ธ

public class FareService {
    private List<Fare> fares;
    
    public int countFares() {
        return fares.size();  // ๐Ÿ’ฅ NullPointerException
    }
}

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋ชจ๋ฅด๋ฉด:

  • "์™œ null์ธ์ง€ ๋ชจ๋ฅด๊ฒ ์–ด์š”"
  • ๊ทธ๋ƒฅ if ์ฒดํฌ๋กœ ํšŒํ”ผ

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์•Œ๋ฉด:

  • fares ๋Š” ์ฐธ์กฐ ๋ณ€์ˆ˜ (Stack ๋˜๋Š” Heap์˜ ๊ฐ์ฒด ์•ˆ)
  • ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” Heap ์˜ List ๊ฐ์ฒด๊ฐ€ ์—†์Œ = null
  • ์ดˆ๊ธฐํ™” ์•ˆ ํ•จ โ†’ null
  • โ†’ ๊ทผ๋ณธ ์›์ธ ํŒŒ์•…

์‹œ๋‚˜๋ฆฌ์˜ค 2: ArrayList์˜ ์˜์™ธ์˜ ๋™์ž‘

public void process(List<Integer> list) {
    list.add(100);  // ํ˜ธ์ถœ์ž์˜ list์—๋„ ์˜ํ–ฅ?
}

List<Integer> myList = new ArrayList<>();
process(myList);
System.out.println(myList);  // [100] โš ๏ธ ๋ณ€๊ฒฝ๋จ!

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋ชจ๋ฅด๋ฉด:

  • "๊ฐ’์ด ๋ณต์‚ฌ๋œ๋‹ค๊ณ  ํ–ˆ๋Š”๋ฐ ์™œ ๋ณ€๊ฒฝ๋˜์ง€?"

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์•Œ๋ฉด:

  • myList ๋Š” Stack์˜ ์ฐธ์กฐ ๋ณ€์ˆ˜
  • Heap์— ArrayList ๊ฐ์ฒด 1๊ฐœ
  • process(myList) โ†’ ์ฐธ์กฐ์˜ ๊ฐ’ ์ด ๋ณต์‚ฌ๋˜์–ด ์ „๋‹ฌ
  • ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ list ์™€ ์™ธ๋ถ€์˜ myList ๊ฐ€ ๊ฐ™์€ Heap ๊ฐ์ฒด ๊ฐ€๋ฆฌํ‚ด
  • โ†’ ํ•œ์ชฝ์—์„œ ๋ณ€๊ฒฝ ์‹œ ์–‘์ชฝ์—์„œ ๋ณด์ž„

โ†’ Pass by Value์˜ ์ง„์‹ค (Unit 4.2 ๋ฏธ๋ฆฌ๋ณด๊ธฐ).


์‹œ๋‚˜๋ฆฌ์˜ค 3: OutOfMemoryError

List<byte[]> leaks = new ArrayList<>();
while (true) {
    leaks.add(new byte<[1024 * 1024]);  // 1MB์”ฉ ์ถ”๊ฐ€
}
// ๐Ÿ’ฅ OutOfMemoryError: Java heap space

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋ชจ๋ฅด๋ฉด:

  • "๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑํ•˜๋Œ€์š”. ์–ด๋–ป๊ฒŒ ๋Š˜๋ ค์š”?"

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์•Œ๋ฉด:

  • Heap ์˜์—ญ์˜ ์ตœ๋Œ€ ํฌ๊ธฐ ์ดˆ๊ณผ
  • leaks ๊ฐ€ GC ๋Œ€์ƒ ์•ˆ ๋จ (์ฐธ์กฐ ์‚ด์•„์žˆ์Œ)
  • -Xmx ์˜ต์…˜์œผ๋กœ Heap ์ฆ๊ฐ€ ๊ฐ€๋Šฅ
  • ๊ทธ๋Ÿฌ๋‚˜ ๊ทผ๋ณธ ํ•ด๊ฒฐ = ๋ถˆํ•„์š”ํ•œ ์ฐธ์กฐ ์ œ๊ฑฐ

โ†’ 5์ฃผ์ฐจ GC ํ•™์Šต์˜ ํ† ๋Œ€.


์‹œ๋‚˜๋ฆฌ์˜ค 4: StackOverflowError

public void recursion() {
    recursion();  // ๋ฌดํ•œ ์žฌ๊ท€
}
recursion();  // ๐Ÿ’ฅ StackOverflowError

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋ชจ๋ฅด๋ฉด:

  • "์™œ OutOfMemoryError๊ฐ€ ์•„๋‹Œ StackOverflowError?"

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์•Œ๋ฉด:

  • ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ๋งˆ๋‹ค Stack์— ํ”„๋ ˆ์ž„ ์ถ”๊ฐ€
  • Stack ์ตœ๋Œ€ ํฌ๊ธฐ ์ดˆ๊ณผ โ†’ StackOverflowError
  • Stack์€ Heap๊ณผ ๋ณ„๋„ ์˜์—ญ
  • โ†’ ์Šค๋ ˆ๋“œ๋ณ„๋กœ ๋‹ค๋ฆ„

์‹œ๋‚˜๋ฆฌ์˜ค 5: ๋™์‹œ์„ฑ ๋ฒ„๊ทธ

public class Counter {
    private int count = 0;
    
    public void increment() {
        count++;  // ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๋ฌธ์ œ
    }
}

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋ชจ๋ฅด๋ฉด:

  • "์™œ ๊ฐ€๋” ๊ฒฐ๊ณผ๊ฐ€ ์ด์ƒํ•˜์ง€?"
  • "synchronized ๋ถ™์ด๋ฉด ๋˜๊ฒ ์ง€"

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์•Œ๋ฉด:

  • count ๋Š” Heap ์˜ ๊ฐ์ฒด์— ์†ํ•œ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜
  • ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ๊ฐ์ฒด ์ ‘๊ทผ ๊ฐ€๋Šฅ (Heap ๊ณต์œ )
  • ๊ฐ ์Šค๋ ˆ๋“œ์˜ Stack์—์„œ ์ž„์‹œ ๋ณ€์ˆ˜๋กœ ์ฒ˜๋ฆฌ โ†’ ์ถฉ๋Œ
  • โ†’ JVM Memory Model, Happens-before ๋“ฑ ๊นŠ์€ ์ฃผ์ œ

โ†’ 4์ฃผ์ฐจ ๋™์‹œ์„ฑ ํ•™์Šต์˜ ํ† ๋Œ€.


์‹œ๋‚˜๋ฆฌ์˜ค 6: ๋ฉด์ ‘ ํƒˆ๋ฝ

"JVM ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”"

๋Œ€๋‹ต ๋ชปํ•จ:

  • "Heap์ด๋ž‘ Stack์ด ์žˆ๋Š” ๊ฑฐ ๊ฐ™์€๋ฐ..."
  • โ†’ ์‹œ๋‹ˆ์–ด ์ž๊ฒฉ ํƒˆ๋ฝ

์ž˜ ๋‹ตํ•จ:

  • "JVM์€ 5๊ฐ€์ง€ ์˜์—ญ์œผ๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค. Method Area, Heap, Stack, PC Register, Native Method Stack..."
  • ๊ฐ ์˜์—ญ์˜ ์—ญํ• , ๊ณต์œ  ์—ฌ๋ถ€, ์ €์žฅ ๋Œ€์ƒ ์„ค๋ช…
  • โ†’ ์‹œ๋‹ˆ์–ด ํ›„๋ณด๋กœ ์ธ์‹

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ์˜ ์ค‘์š”์„ฑ

์ง€๊ธˆ ํ•™์Šต ์•ˆ ํ•˜๋ฉด:

  • Pass by Value (4.2) ์ดํ•ด X
  • ๋™์‹œ์„ฑ (4์ฃผ์ฐจ) ์ดํ•ด X
  • GC (5์ฃผ์ฐจ) ์ดํ•ด X
  • JPA ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ (12์ฃผ์ฐจ) ์ดํ•ด X
  • ๋ฉด์ ‘์—์„œ ๋ฌด๋„ˆ์ง

โ†’ ์ด Unit์ด ํ–ฅํ›„ ๋ชจ๋“  ์ž๋ฐ” ํ•™์Šต์˜ ํ† ๋Œ€.


โœ… 4. ํ•ด๊ฒฐ์ฑ… โ€” JVM ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ 5๊ฐ€์ง€

์ „์ฒด ๊ตฌ์กฐ๋„ โญ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚              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 โ”‚          โ”‚ โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
โ”‚         (์Šค๋ ˆ๋“œ๋ณ„ ๋ถ„๋ฆฌ)                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

1. Method Area โญ (Metaspace, Java 8+)

์—ญํ• : ํด๋ž˜์Šค ์ •๋ณด ์ €์žฅ

์ €์žฅ ๋‚ด์šฉ:

  • ํด๋ž˜์Šค์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ (์ด๋ฆ„, ๋ถ€๋ชจ, ์ธํ„ฐํŽ˜์ด์Šค)
  • ๋ฉ”์„œ๋“œ ์ฝ”๋“œ (๋ฐ”์ดํŠธ์ฝ”๋“œ)
  • ํ•„๋“œ ์ •๋ณด (์ด๋ฆ„, ํƒ€์ž…)
  • static ๋ณ€์ˆ˜ โญ
  • ์ƒ์ˆ˜ ํ’€ (Constant Pool) โ€” ๋ฆฌํ„ฐ๋Ÿด ๋“ฑ

ํŠน์ง•:

  • ๋ชจ๋“  ์Šค๋ ˆ๋“œ ๊ณต์œ 
  • JVM ์‹œ์ž‘ ์‹œ ์ƒ์„ฑ
  • ํ•œ ๋ฒˆ ๋กœ๋“œ๋˜๋ฉด ๊ฑฐ์˜ ์•ˆ ๋ฐ”๋€œ
  • Java 7๊นŒ์ง€: PermGen (์˜๊ตฌ ์˜์—ญ)
  • Java 8+: Metaspace (๋„ค์ดํ‹ฐ๋ธŒ ๋ฉ”๋ชจ๋ฆฌ)

์˜ˆ์‹œ:

public class Customer {
    public static int count = 0;  // Method Area์—
    private String name;          // ๊ฐ์ฒด ๋งˆ๋‹ค (Heap์—)
    
    public void hello() { ... }   // ๋ฉ”์„œ๋“œ ์ฝ”๋“œ โ†’ Method Area
}

2. Heap โญโญ (๊ฐ€์žฅ ์ค‘์š”)

์—ญํ• : ๋ชจ๋“  ๊ฐ์ฒด ์ €์žฅ

์ €์žฅ ๋‚ด์šฉ:

  • new ๋กœ ๋งŒ๋“  ๋ชจ๋“  ๊ฐ์ฒด
  • ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜
  • ๋ฐฐ์—ด

ํŠน์ง•:

  • ๋ชจ๋“  ์Šค๋ ˆ๋“œ ๊ณต์œ 
  • ๊ฐ€์žฅ ํฐ ์˜์—ญ
  • GC ์˜ ์ฃผ ๋Œ€์ƒ (5์ฃผ์ฐจ ํ•™์Šต)
  • -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์— ์žˆ๋Š” ์ฐธ์กฐ ๋ณ€์ˆ˜

3. Stack โญโญ (๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์˜ ๋ฌด๋Œ€)

์—ญํ• : ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์ •๋ณด, ์ง€์—ญ๋ณ€์ˆ˜

์ €์žฅ ๋‚ด์šฉ:

  • Stack Frame (๋ฉ”์„œ๋“œ ํ˜ธ์ถœ๋งˆ๋‹ค 1๊ฐœ)
  • ์ง€์—ญ๋ณ€์ˆ˜
  • ๋ฉ”์„œ๋“œ ๋งค๊ฐœ๋ณ€์ˆ˜
  • ๋ฆฌํ„ด ์ฃผ์†Œ

ํŠน์ง•:

  • ์Šค๋ ˆ๋“œ๋ณ„๋กœ ๋”ฐ๋กœ โญ
  • LIFO (Last In, First Out)
  • ๋งค์šฐ ๋น ๋ฆ„
  • ๋ฉ”์„œ๋“œ ์ข…๋ฃŒ โ†’ ํ”„๋ ˆ์ž„ ์ž๋™ ์ œ๊ฑฐ

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 ์ œ๊ฑฐ
}

4. PC Register

์—ญํ• : ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ๋ช…๋ น์˜ ์ฃผ์†Œ

ํŠน์ง•:

  • ์Šค๋ ˆ๋“œ๋ณ„๋กœ ๋”ฐ๋กœ
  • ๋งค์šฐ ์ž‘์Œ (1๊ฐœ ์ฃผ์†Œ๋งŒ ์ €์žฅ)
  • "์ง€๊ธˆ ์–ด๋А ๋ช…๋ น ์‹คํ–‰ ์ค‘?" ์ถ”์ 

์˜ˆ์‹œ:

public void method() {
    int x = 1;   // PC: line 1
    int y = 2;   // PC: line 2
    int z = x + y; // PC: line 3
}

โ†’ ์Šค๋ ˆ๋“œ ์ „ํ™˜ ์‹œ ์–ด๋””๊นŒ์ง€ ํ–ˆ๋Š”์ง€ ๊ธฐ์–ตํ•˜๋Š” ์šฉ๋„.


5. Native Method Stack

์—ญํ• : ๋„ค์ดํ‹ฐ๋ธŒ ๋ฉ”์„œ๋“œ (C/C++) ํ˜ธ์ถœ ์ •๋ณด

์ €์žฅ ๋‚ด์šฉ:

  • ์ž๋ฐ” ์™ธ ์–ธ์–ด๋กœ ์ž‘์„ฑ๋œ ๋ฉ”์„œ๋“œ์˜ ํ˜ธ์ถœ ์ •๋ณด

ํŠน์ง•:

  • ์Šค๋ ˆ๋“œ๋ณ„
  • JNI (Java Native Interface) ํ˜ธ์ถœ ์‹œ ์‚ฌ์šฉ

์˜ˆ์‹œ:

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์Šค๋ ˆ๋“œ๋ณ„๋„ค์ดํ‹ฐ๋ธŒ ํ˜ธ์ถœ์ž‘์Œ์Šค๋ ˆ๋“œ ์‹œ์ž‘

๋ณ€์ˆ˜์˜ ์ข…๋ฅ˜์™€ ์ €์žฅ ์œ„์น˜ โญโญ (์ž๊ธฐ ์ ๊ฒ€ Q2)

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 Area
  • โ‘ก name (์ธ์Šคํ„ด์Šค) โ†’ Heap (๊ฐ์ฒด ์•ˆ)
  • โ‘ข localVar (์ง€์—ญ, ๊ธฐ๋ณธํ˜•) โ†’ Stack
  • โ‘ฃ other (์ง€์—ญ ์ฐธ์กฐ) โ†’ Stack (์ฐธ์กฐ), Heap (๊ฐ์ฒด)

โ†’ ๋ฉด์ ‘์—์„œ ์ž์ฃผ ๋ฌป๋Š” ์งˆ๋ฌธ.


๐Ÿ—๏ธ 5. ๋‚ด๋ถ€ ๋™์ž‘ ์›๋ฆฌ

ํด๋ž˜์Šค ๋กœ๋”ฉ ๊ณผ์ • โญ

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 condition
  • localValue ๋Š” ๊ฐ ์Šค๋ ˆ๋“œ์˜ Stack ์— ๋”ฐ๋กœ โ†’ ์•ˆ์ „

โ†’ 4์ฃผ์ฐจ ๋™์‹œ์„ฑ ํ•™์Šต์˜ ํ† ๋Œ€.


Java 8 ์˜ ๋ณ€ํ™” โ€” PermGen โ†’ Metaspace โญ

Java 7 ๊นŒ์ง€:

[JVM Heap]
  โ”œโ”€โ”€ Young Generation
  โ”œโ”€โ”€ Old Generation
  โ””โ”€โ”€ PermGen (์˜๊ตฌ ์˜์—ญ)  โ† Method Area์˜ ์ผ๋ถ€
       - ํด๋ž˜์Šค ์ •๋ณด
       - static ๋ณ€์ˆ˜
       - ์ƒ์ˆ˜ ํ’€

๋ฌธ์ œ:

  • PermGen ํฌ๊ธฐ ๊ณ ์ • โ†’ OutOfMemoryError: PermGen space ์ž์ฃผ ๋ฐœ์ƒ
  • ๋™์  ํด๋ž˜์Šค ๋กœ๋”ฉ (Spring, JSP ๋“ฑ) ์‹œ ๋ถ€์กฑ

Java 8+:

[JVM Heap]
  โ”œโ”€โ”€ Young Generation
  โ””โ”€โ”€ Old Generation

[Native Memory]
  โ””โ”€โ”€ Metaspace  โ† Method Area
       - ๋™์  ํฌ๊ธฐ ์กฐ์ • (OS ๋ฉ”๋ชจ๋ฆฌ ํ•œ๋„๊นŒ์ง€)
       - ๋” ์•ˆ์ •์ 

ํšจ๊ณผ:

  • OutOfMemoryError: PermGen space ์‚ฌ๋ผ์ง
  • ๋Œ€์‹  OutOfMemoryError: Metaspace ๊ฐ€๋Šฅ (๋“œ๋ฌธ ์ผ)

โ†’ ๋ฉด์ ‘ ๋นˆ์ถœ ์งˆ๋ฌธ: "Java 8 ์ดํ›„ ๋ฉ”๋ชจ๋ฆฌ ๋ณ€ํ™”?"


String Constant Pool โญ

๋ฌธ์ž์—ด์€ ํŠน๋ณ„ ์ทจ๊ธ‰:

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 ํ•™์Šต ์œผ๋กœ ์—ฐ๊ฒฐ.


๐Ÿ’ป 6. ์‹ค์ „ ์ฝ”๋“œ ์˜ˆ์‹œ

์˜ˆ์‹œ 1: ๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜ ์ถ”์ 

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 Area
  • VERSION โ†’ Method Area + String Pool
  • id, amount, status โ†’ Heap (๊ฐ ์ธ์Šคํ„ด์Šค๋งˆ๋‹ค)
  • changeAmount ๋ฉ”์„œ๋“œ ์ฝ”๋“œ โ†’ Method Area
  • newAmount, oldAmount โ†’ Stack (ํ˜ธ์ถœ ์‹œ)

์˜ˆ์‹œ 2: ๊ฐ์ฒด ์ƒ์„ฑ๊ณผ ๋ฉ”๋ชจ๋ฆฌ

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 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

์˜ˆ์‹œ 3: Stack Overflow ์˜ˆ์‹œ

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?:

  • ๋งค ํ˜ธ์ถœ๋งˆ๋‹ค Stack Frame ์ถ”๊ฐ€
  • Stack ํฌ๊ธฐ ํ•œ๊ณ„ (๋ณดํ†ต 512KB ~ 1MB) ์ดˆ๊ณผ
  • โ†’ ๋™์  ๊ณ„ํš๋ฒ• ๋“ฑ์œผ๋กœ ํ•ด๊ฒฐ

ํ•ด๊ฒฐ:

// ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ
public static int factorial(int n) {
    int result = 1;
    for (int i = 2; i <= n; i++) {
        result *= i;
    }
    return result;
}

โ†’ Stack์„ ๊ฑฐ์˜ ์•ˆ ์”€.


์˜ˆ์‹œ 4: Heap OutOfMemory ์˜ˆ์‹œ

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).


์˜ˆ์‹œ 5: ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ๋ฉ”๋ชจ๋ฆฌ

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 ๋‹จ๊ณ„
  • ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ read ์‹œ ๊ฐ™์€ ๊ฐ’ โ†’ ํ•œ ๋ฒˆ ์ฆ๊ฐ€ ๋ˆ„๋ฝ
  • โ†’ race condition

ํ•ด๊ฒฐ:

private AtomicInteger count = new AtomicInteger(0);
// ๋˜๋Š” synchronized

โ†’ 4์ฃผ์ฐจ ๋™์‹œ์„ฑ์—์„œ ๋ณธ๊ฒฉ.


โš ๏ธ 7. ์ฃผ์˜์‚ฌํ•ญ & ํ”ํ•œ ์‹ค์ˆ˜

์‹ค์ˆ˜ 1: "Stack๊ณผ Heap" ๋งŒ ์•ˆ๋‹ค

Q: "JVM ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ?"
A: "Stack๊ณผ Heap์ด์š”"

โ†’ 5๊ฐ€์ง€ ์˜์—ญ ์ค‘ 2๊ฐœ๋งŒ. ๋ฉด์ ‘์—์„œ ๊นŠ์ด ๋ถ€์กฑ ๋…ธ์ถœ.

์˜ฌ๋ฐ”๋ฅธ ๋‹ต: Method Area, Heap, Stack, PC Register, Native Method Stack โ€” 5๊ฐ€์ง€ + ๊ฐ๊ฐ์˜ ์—ญํ• .


์‹ค์ˆ˜ 2: static ๋ณ€์ˆ˜๊ฐ€ Heap์ด๋ผ๊ณ  ํ•จ

Q: "static ๋ณ€์ˆ˜๋Š” ์–ด๋””์—?"
A: "Heap์ด์š”" โŒ

์ •๋‹ต: Method Area (Java 8+ Metaspace).

์ด์œ :

  • static ์€ ํด๋ž˜์Šค์— ์†ํ•จ
  • ํด๋ž˜์Šค ์ •๋ณด๊ฐ€ Method Area์— ์ €์žฅ
  • ์ธ์Šคํ„ด์Šค ๋งŒ๋“ค์ง€ ์•Š์•„๋„ ์กด์žฌ
Customer.totalCount;  // ์ธ์Šคํ„ด์Šค ์—†์ด ์ ‘๊ทผ
                      // โ†’ Method Area์— ์žˆ์–ด์•ผ ๊ฐ€๋Šฅ

์‹ค์ˆ˜ 3: ๋ชจ๋“  ๊ฐ์ฒด๊ฐ€ Heap์ด๋ผ๊ณ  ๋‹จ์ˆœํ™”

Q: "๊ฐ์ฒด๋Š” ์–ด๋””์— ์ €์žฅ?"
A: "Heap" โŒ (ํ‹€๋ฆฐ ๊ฑด ์•„๋‹ˆ์ง€๋งŒ ๋ถ€์ •ํ™•)

๋ณด๋‹ค ์ •ํ™•ํ•œ ๋‹ต:

  • ์ธ์Šคํ„ด์Šค ๊ฐ์ฒด โ†’ Heap
  • ๊ฐ์ฒด์˜ ์ฐธ์กฐ ๋ณ€์ˆ˜ โ†’ Stack (์ง€์—ญ๋ณ€์ˆ˜๋ฉด) ๋˜๋Š” Heap (ํ•„๋“œ๋ฉด)
  • ํด๋ž˜์Šค ์ •๋ณด ์ž์ฒด โ†’ Method Area

์‹ค์ˆ˜ 4: PermGen ๊ณผ Metaspace ํ˜ผ๋™

Q: "Java 8 ์ดํ›„ PermGen์€?"
A: "PermGen์ด ๋” ์ปค์กŒ์–ด์š”" โŒ

์ •๋‹ต: PermGen์ด ์‚ฌ๋ผ์ง€๊ณ  Metaspace๋กœ ๊ต์ฒด.

  • Java 7๊นŒ์ง€: PermGen (Heap ์ผ๋ถ€, ๊ณ ์ • ํฌ๊ธฐ)
  • Java 8+: Metaspace (Native Memory, ๋™์  ํฌ๊ธฐ)

์‹ค์ˆ˜ 5: Stack ํฌ๊ธฐ๋ฅผ Heap ์ฒ˜๋Ÿผ ํฐ ์ค„ ์•ˆ๋‹ค

public void recursion(int depth) {
    // 1๋งŒ ๋ฒˆ ์žฌ๊ท€
    if (depth < 10000) recursion(depth + 1);
}
recursion(0);  // ๐Ÿ’ฅ StackOverflowError ๊ฐ€๋Šฅ

โ†’ Stack์€ ์ˆ˜๋ฐฑ KB ~ ์ˆ˜ MB. Heap (์ˆ˜ GB) ์™€ ๋งค์šฐ ๋‹ค๋ฆ„.


์‹ค์ˆ˜ 6: ์ง€์—ญ๋ณ€์ˆ˜๋„ GC ๋Œ€์ƒ์ด๋ผ๊ณ  ํ•จ

Q: "์ง€์—ญ๋ณ€์ˆ˜๊ฐ€ GC ๋Œ€์ƒ?"
A: "๋„ค" โŒ

์ •๋‹ต: ์ง€์—ญ๋ณ€์ˆ˜๋Š” ๋ฉ”์„œ๋“œ ์ข…๋ฃŒ ์‹œ ์ž๋™ ์ œ๊ฑฐ (Stack Frame ์ œ๊ฑฐ). GC ๋Œ€์ƒ ์•„๋‹˜.

public void method() {
    int x = 10;  // Stack ์—
    String s = "hello";  // s๋Š” Stack์˜ ์ฐธ์กฐ, "hello"๋Š” ๋ณ„๋„
}
// ๋ฉ”์„œ๋“œ ์ข…๋ฃŒ โ†’ x, s ์ž๋™ ์ œ๊ฑฐ

GC ๋Œ€์ƒ์€ Heap ์˜ ๊ฐ์ฒด ๋งŒ.


์‹ค์ˆ˜ 7: "JVM ์˜ต์…˜์€ 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 ์‹œ ๋คํ”„

๐Ÿ”— 8. ์—ฐ๊ด€ ๊ฐœ๋… ๋งต

Phase 4 (JVM ๋ฉ”๋ชจ๋ฆฌ) ๋‚ด ํ๋ฆ„

[Unit 4.1: JVM ๋Ÿฐํƒ€์ž„ ๋ฐ์ดํ„ฐ ์˜์—ญ]  โ† ์ง€๊ธˆ ์—ฌ๊ธฐ
        โ†“
[Unit 4.2: Pass by Value (์ž๋ฐ”์˜ ์ง„์‹ค)]
   ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์œ„์—์„œ ๊ฐ’/์ฐธ์กฐ ์ „๋‹ฌ ์ดํ•ด

Phase 4์˜ ์˜๋ฏธ:

  • Phase 1-3: "์–ด๋–ป๊ฒŒ ์„ค๊ณ„ํ• ๊นŒ" (๋…ผ๋ฆฌ)
  • Phase 4: "์–ด๋–ป๊ฒŒ ๋™์ž‘ํ• ๊นŒ" (๋ฌผ๋ฆฌ)

Phase 2์™€์˜ ํ†ตํ•ฉ

์ด์ „ ํ•™์Šต ๋‹ค์‹œ ๋ณด๊ธฐ:

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):

  • Heap์˜ ๊ฐ์ฒด ์ˆ˜๊ฑฐ ๋ฉ”์ปค๋‹ˆ์ฆ˜
  • Young/Old Generation
  • โ†’ Heap ์ดํ•ด ํ•„์ˆ˜

Phase 6 (String, ์ปฌ๋ ‰์…˜):

  • String Constant Pool
  • ArrayList vs LinkedList์˜ ๋ฉ”๋ชจ๋ฆฌ ์ฐจ์ด

Phase 7 (I/O):

  • ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํŒŒ์ผ/๋„คํŠธ์›Œํฌ๋กœ

4์ฃผ์ฐจ (๋™์‹œ์„ฑ):

  • ์Šค๋ ˆ๋“œ๋ณ„ Stack vs ๊ณต์œ  Heap
  • Memory Model, Happens-before
  • volatile, synchronized

5์ฃผ์ฐจ (Spring):

  • Bean ๋“ค์ด Heap์— ์–ด๋–ป๊ฒŒ ์ €์žฅ๋˜๋‚˜
  • Singleton ์˜ ์˜๋ฏธ

11-12์ฃผ์ฐจ (JPA):

  • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๊ฐ€ Heap์—
  • 1์ฐจ ์บ์‹œ = Heap์˜ Map

17์ฃผ์ฐจ (MSA):

  • ๊ฐ ์„œ๋น„์Šค๊ฐ€ ๋ณ„๋„ JVM
  • ๋ณ„๋„ Heap, Method Area

โ†’ ๋ชจ๋“  ์ž๋ฐ” ํ•™์Šต์˜ ํ† ๋Œ€.


Java ๋ฉ”๋ชจ๋ฆฌ ์ง„ํ™”

[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

๐Ÿ“ 9. ํ•ต์‹ฌ ์š”์•ฝ โ€” 3์ค„ ์ •๋ฆฌ

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) ๋กœ ๊ฐ ์˜์—ญ ํ†ต์ œ ๊ฐ€๋Šฅ.


๐ŸŽ“ ํ•™์Šต ์ž๊ธฐ ์ ๊ฒ€

๊ธฐ๋ณธ ์ดํ•ด

  • JVM ์˜ 5๊ฐ€์ง€ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ๋‚˜์—ดํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๊ฐ ์˜์—ญ์˜ ๊ณต์œ  ์—ฌ๋ถ€ (์Šค๋ ˆ๋“œ๋ณ„/๊ณต์œ ) ๋ฅผ ์•ˆ๋‹ค
  • static ๋ณ€์ˆ˜, ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜, ์ง€์—ญ๋ณ€์ˆ˜์˜ ์ €์žฅ ์œ„์น˜๋ฅผ ๊ตฌ๋ณ„ํ•œ๋‹ค
  • Java 8 ์ดํ›„ PermGen โ†’ Metaspace ๋ณ€ํ™”๋ฅผ ์•ˆ๋‹ค

์‹ค์ „ ์ ์šฉ

  • ILIC ์ฝ”๋“œ์˜ ๋ณ€์ˆ˜๋“ค์ด ์–ด๋””์— ์ €์žฅ๋˜๋Š”์ง€ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๋‹ค
  • StackOverflowError ์™€ OutOfMemoryError ์˜ ์ฐจ์ด๋ฅผ ์•ˆ๋‹ค
  • JVM ์˜ต์…˜์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์‹œ ๋ฉ”๋ชจ๋ฆฌ ๊ณต์œ  ์œ„ํ—˜์„ ์ธ์‹ํ•œ๋‹ค

๋ฉด์ ‘ ๋Œ€๋น„ (3-5๋ถ„ ๋‹ต๋ณ€)

  • "JVM ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ
  • "static ๋ณ€์ˆ˜๋Š” ์–ด๋””์—?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ
  • "Java 8 ์ดํ›„ PermGen ๋ณ€ํ™”?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ
  • "Stack๊ณผ Heap์˜ ๊ฒฐ์ •์  ์ฐจ์ด?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ

์ž๊ธฐ ์ ๊ฒ€ ์งˆ๋ฌธ ๋‹ต๋ณ€

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() ๋กœ ์ƒ์„ฑ๋œ ๊ฒƒ):

  • ํ•ญ์ƒ Heap
  • new ํ‚ค์›Œ๋“œ = "Heap์— ๊ฐ์ฒด ์ƒ์„ฑ"

๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ฆผ (Case 1):

[Stack โ€” ๋ฉ”์„œ๋“œ Frame]
  m (์ฐธ์กฐ) โ”€โ”€โ”€โ”€โ”€โ”
                โ”‚
[Heap]          โ”‚
  Member ์ธ์Šคํ„ด์Šค โ—„โ”€โ”˜
   - ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋“ค

m == ๊ฐ์ฒด ๋ณธ์ฒด ๊ฐ€ ์•„๋‹˜:

  • m ์€ ์ฐธ์กฐ ๋ณ€์ˆ˜ (๊ฐ์ฒด์˜ ์ฃผ์†Œ๋ฅผ ๋‹ด์Œ)
  • ๊ฐ์ฒด ๋ณธ์ฒด๋Š” ๋ณ„๋„๋กœ Heap์— ์กด์žฌ
  • โ†’ Java์˜ ๊ฐ์ฒด ๋ณ€์ˆ˜๋Š” ํ•ญ์ƒ ์ฐธ์กฐ (C ์˜ ํฌ์ธํ„ฐ์™€ ๋น„์Šท)

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 AreaHeap (๊ฐ์ฒด ์•ˆ)
์ˆ˜๋ช…ํด๋ž˜์Šค ๋กœ๋“œ ~ JVM ์ข…๋ฃŒ๊ฐ์ฒด ์ƒ์„ฑ ~ GC
์ ‘๊ทผํด๋ž˜์Šค๋ช….๋ณ€์ˆ˜์ธ์Šคํ„ด์Šค.๋ณ€์ˆ˜
GC์ผ๋ฐ˜์ ์œผ๋กœ X๊ฐ์ฒด GC ์‹œ ํ•จ๊ป˜

์™œ ์ด๋ ‡๊ฒŒ ๋‹ค๋ฅธ๊ฐ€?:

  • static ์€ ํด๋ž˜์Šค์— ์†ํ•จ โ†’ ์ธ์Šคํ„ด์Šค ์—†์ด ์กด์žฌ ๊ฐ€๋Šฅ
  • ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋Š” ๊ฐ์ฒด์— ์†ํ•จ โ†’ ๊ฐ์ฒด๋งˆ๋‹ค ๋”ฐ๋กœ ํ•„์š”

์‹ค์šฉ์  ํ•จ์˜:

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 ์€ ๊ณต์œ  โ†’ 3
  • myCount ๋Š” ๊ฐ์ž โ†’ c1: 2, c2: 1

โ†’ static ์˜ ๋ณธ์งˆ์ด ๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜์—์„œ ๋“œ๋Ÿฌ๋‚จ.

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์‹œ ์œ„ํ—˜ โš ๏ธ :

  • static ๋ณ€์ˆ˜๋Š” ๋ชจ๋“  ์Šค๋ ˆ๋“œ ๊ณต์œ 
  • ๋™๊ธฐํ™” ์—†์ด ๋ณ€๊ฒฝ ์‹œ race condition
  • โ†’ 4์ฃผ์ฐจ ๋™์‹œ์„ฑ์—์„œ ๋ณธ๊ฒฉ.

๋‹ค์Œ Unit์œผ๋กœ

  • Pass by Value (์ž๋ฐ”์˜ ์ง„์‹ค) ์„ ํ•™์Šตํ•  ์ค€๋น„ ์™„๋ฃŒ
  • "์ž๋ฐ”๋Š” ์ •๋ง Pass by Value ์ธ๊ฐ€?" ์˜ ์ง„์‹ค์ด ๊ถ๊ธˆํ•˜๋‹ค
  • ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์œ„์—์„œ ๊ฐ’/์ฐธ์กฐ ์ „๋‹ฌ์„ ์ดํ•ดํ•  ์ค€๋น„ ์™„๋ฃŒ
profile
Software Developer

0๊ฐœ์˜ ๋Œ“๊ธ€