[Java] 25. JVM (Java Virtual Machine)

백하림's avatar
Feb 06, 2025
[Java] 25. JVM (Java Virtual Machine)
변수 (int, double, boolean, String)
static - (메인이 실행되기 전에 메모리에 로드 된다.) - 공간 분리 (class별로 분리되 있음.)
static은 정적이고, 한 개만 메모리에 로드 된다.
메소드 (함수) - 4가지 유형 (기본, 인수 1개, 인수가 여러 개 있는, 리턴이 있는) void (리턴이 없는)

1. heap (힙)

  • new가 되면 static이 붙지 않은 모든(변수, 메소드)가 heap에 로드 된다.
  • 메소드 내부에서 선언된 지역 변수(primitive 타입 등)는 Stack에 저장되지만, 키워드로 생성된 객체는 Heap에 저장됨.
package jvm; class Student { //이 3가지를 저장할 수 있는 건 class 밖에 없음 int no; String name; int age; void show() { System.out.println(no); System.out.println(name); System.out.println(age); System.out.println("================"); } } public class Heap01 { public static void main(String[] args) { Student s1 = new Student(); // new가 되면 static이 붙지 않은 모든(변수, 메소드)가 heap에 로드 된다. s1.no = 1; s1.name = "홍길동"; s1.age = 18; s1.show(); Student s2 = new Student(); s2.no = 2; s2.name = "백하림"; s2.age = 29; s2.show(); } }
notion image

2. stack (스택) (LIFO, Last-In First-Out)

  • 메소드 실행 시 Stack에 push (쌓임)
  • 메소드 종료 시 Stack에서 pop (빠짐)
  • 후입선출(LIFO, Last-In First-Out) 방식
package jvm; public class Stack01 { static void m1() { // 함수의 바디는 호출 시에 실행된다. int a = 1; m2(); } static void m2() { int b = 1; } public static void main(String[] args) { Stack01 s = new Stack01();// static이 안 붙어있는 것만 출력 System.out.println("10번 라인"); m1(); System.out.println("12번 라인"); } }
notion image

3. Stack Overflow(스택 오버플로우)

이 코드는 무한 재귀 호출로 인해 **Stack Overflow(스택 오버플로우)**가 발생하는 예제다.
 
Stack Overflow : 종료 조건 없이 무한 재귀하면 Stack 메모리가 꽉 차서 발생
해결 방법 : 종료 조건(기저 사례, Base Case) 추가
package jvm; public class Stack02 { // 오류는 위에서 터져서 아래 또한 다 터진다. // 오류는 맨 위에서 확인해야 한다. static void m1() { int a = 1; m1(); // 재귀함수 (데몬), 무한 뺑뺑이 그래서 종료 할 수 있는 트리거를 만들어야 함. //오버플로우 발생 } public static void main(String[] args) { m1(); } }
notion image

4. queue (큐) FIFO(First In First Out)

package jvm; public class Queue01 { static void m1() { int n1 = 1; System.out.println("🚒"); // 윈도우 키 + . 하면 이모지 나옴 System.out.println("🏍️"); System.out.println("🚲️"); m2();// m2 System.out.println("🚅️"); System.out.println("✈️"); } static void m2() { int n2 = 2; System.out.println("🍕"); System.out.println("🍔"); System.out.println("🌭"); System.out.println("🥚"); System.out.println("🧀"); } public static void main(String[] args) { System.out.println("main 시작"); m1(); System.out.println("main 종료"); } }
notion image
notion image
1️⃣ main() 실행 → m1() 호출
2️⃣ m1() 실행 중 → m2() 호출
3️⃣ m2() 실행 후 종료 → m1()로 돌아감
4️⃣ m1() 실행 후 종료 → main()으로 돌아감
즉, Stack 구조에서
  • m1() 실행 중에 m2()를 호출하면 m2()가 Stack에 쌓임
  • m2() 실행이 끝나면 Stack에서 제거(pop) 되고, 다시 m1()이 실행됨
💡 결론:
m1()과 m2()는 메소드
메소드가 호출되면 Stack에 쌓였다가 실행 후 사라짐
m1()이 m2()를 호출하면 먼저 m2()가 실행되고, 끝난 후 다시 m1()으로 돌아감
Share article

harimmon