JVM과 내부에서 실행되고 있는 프로그램은 부모 프로세스 - 자식 프로세스 관계를 갖고 있다고 봐도 무방한가요?
아닙니다. JVM과 내부 프로그램은 부모-자식 프로세스 관계가 아니라 하나의 프로세스 안에서 동작하는 구조입니다.
실제 구조
[ 부모-자식 프로세스 (X) ]
┌─── 프로세스 A: JVM ───┐ ┌─── 프로세스 B: Java 앱 ───┐
│ 독립된 메모리 공간 │ │ 독립된 메모리 공간 │
└────────────────────────┘ └──────────────────────────┘
↑ 이렇게 분리되어 있지 않음
[ 실제 구조 (O) ]
┌──────────── 하나의 프로세스 (PID: 1234) ──────────────┐
│ │
│ JVM (실행 엔진 + 메모리 관리) │
│ ┌─────────────────────────────────────────────┐ │
│ │ Java 애플리케이션 │ │
│ │ (바이트코드가 JVM 위에서 실행) │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌── 스레드 ──┐ ┌── 스레드 ──┐ ┌── GC 스레드 ──┐ │
│ │ main │ │ worker-1 │ │ GC thread │ │
│ └────────────┘ └────────────┘ └───────────────┘ │
│ │
└───────────────────────────────────────────────────────┘
OS에서 확인
# java 명령어로 프로그램 실행
$ java -jar app.jar
# 프로세스 확인
$ ps aux | grep java
user 1234 java -jar app.jar ← 프로세스 1개만 존재
# JVM과 앱이 별도 프로세스로 분리되지 않음
# JVM 자체가 곧 이 프로세스
부모-자식 프로세스와의 차이
| 항목 | 부모-자식 프로세스 | JVM + Java 앱 |
|---|---|---|
| 프로세스 수 | 2개 이상 | 1개 |
| PID | 각각 다름 | 동일 |
| 메모리 공간 | 독립 (격리) | 공유 (같은 프로세스) |
| 통신 방식 | IPC (파이프, 소켓 등) | 직접 메모리 접근 |
| 한쪽 종료 시 | 나머지 생존 가능 | JVM 종료 = 앱 종료 |
부모-자식 프로세스 예시
# 쉘에서 명령어 실행 — 진짜 부모-자식
$ bash # PID 1000 (부모)
$ ls # PID 1001 (자식) — 독립 프로세스로 생성
┌── 프로세스 1000: bash ──┐ ┌── 프로세스 1001: ls ──┐
│ 독립된 메모리 공간 │ │ 독립된 메모리 공간 │
│ 자식 종료를 기다림 │ ←→ │ 실행 후 종료 │
└─────────────────────────┘ └──────────────────────┘
fork()로 생성된 별도 프로세스
JVM + Java 앱
┌──── 프로세스 1234: java ────────────────────────┐
│ │
│ JVM 영역 Java 앱 영역 │
│ ┌────────────┐ ┌─────────────────────────┐ │
│ │ Class Loader│ │ main() │ │
│ │ GC │ │ UserService │ │
│ │ JIT │ │ OrderController │ │
│ └────────────┘ └─────────────────────────┘ │
│ │
│ 같은 메모리 공간을 공유 │
└──────────────────────────────────────────────────┘
더 정확한 비유
부모-자식보다는 브라우저와 웹 페이지의 관계에 가깝습니다.
[ 브라우저 비유 ]
┌─── Chrome (하나의 프로세스) ───┐
│ │
│ 렌더링 엔진 (V8) │ ≈ JVM (실행 엔진)
│ ┌──────────────────────┐ │
│ │ 웹 페이지 (JS 실행) │ │ ≈ Java 애플리케이션
│ └──────────────────────┘ │
│ │
│ Chrome 종료 = 웹 페이지 종료 │ JVM 종료 = Java 앱 종료
└────────────────────────────────┘
JVM이 진짜 부모-자식을 만드는 경우
Java에서 외부 프로세스를 실행하면 그때는 부모-자식 관계가 됩니다.
// 이때만 부모-자식 프로세스 관계 성립
Process child = Runtime.getRuntime().exec("ls -la");
┌── 프로세스 1234: java (부모) ──┐
│ JVM + Java 앱 │
│ │ fork + exec │
└──────────┼─────────────────────┘
▼
┌── 프로세스 1235: ls (자식) ────┐
│ 독립된 프로세스 │
└────────────────────────────────┘
핵심 정리
JVM과 Java 애플리케이션은 하나의 프로세스 안에서 동작하며, 부모-자식 프로세스 관계가 아닙니다. JVM은 별도 프로세스가 아니라 프로그램을 실행하는 런타임 환경 그 자체이므로, JVM이 종료되면 애플리케이션도 함께 종료됩니다. "JVM 위에서 돌아간다"는 표현은 별도 프로세스가 아니라 같은 프로세스 내에서 JVM이 제공하는 추상화 위에서 실행된다는 의미입니다.