Java는 JVM 위에서 실행된다.
왜 Java는 JVM위에서 실행이 될까? 그리고 JVM은 무엇일까? 라는 의문이 생긴다.
기본적으로 Java는 프로그래밍 언어이다. 하지만 컴퓨터는 Java를 이해할 수 없다.
컴퓨터는 오직 기계어만을 이해할 수 있다. 그렇기 때문에 Java는 기계어가 아니기 떄문에 컴퓨터는 Java를 이해할 수 없었던 것이다. 컴퓨터가 Java를 이해할 수 있도록 통역해주는 것이 바로 JVM이다.
C 언어는 상황이 다르다. C 언어는 작성한 코드를 바로 기계어로 컴파일하여 실행한다.
머리말에서 간단하게 JVM은 무엇을 하는지 대충 이해는 했을 것이다.
JVM(Java Virtual Machine) 정의
자바 바이트코드를 실행하고, 메모리를 관리하며, OS와 하드웨어 차이를 추상화하는 실행 환경이다.
JVM의 역활은 크게 3가지로 분류한다.
Java 코드 → 컴파일 → Bytecode (.class) → JVM → Native Code → OS → CPU 실행
C 코드 → 컴파일 → Native Code (기계어) → OS → CPU 실행
가장 먼저 C 언어 방식에 대해서 간단하게 확인을 하면 대충 JVM 구조를 이해할 수 있을 것이다.
일반적으로 C를 사용하여 파일을 생성할 경우 각 OS마다 여러 번의 컴파일이 필요하게 된다.
윈도우 - .exe
Linux - ELF
...
Java는 중간에 JVM을 사용하여 여러 환경에서도 한 번의 컴파일로 사용할 수 있도록 설계를 했디.
Java → JVM → OS
JVM 설계 철학
Write Once, Run Anywhere
OS위에 JVM을 둔 이유는 다음과 같다
JVM이 공통 포멧인 Bytecode으로 실행을 담당하여 OS에 영향읋 받지 않는 플랫폼의 독립성, GC 자동 관리와 메모리 접근 제한으로 안정성, 메모리 해제와 실행 환경 / OS에 대한 신경 제거하여 생산성을 얻는다는 의도가 있다.
준비 단계
ClassLoaderSubsystem에서 파일을 읽어 JVM에 적재를 한다.
Runtime Data Area
해당 구간은 가장 핵심인 구간이다.
구성요소는 method area, heap, java stack, pc register, native stack으로 구성되어 있다.
실행 단계
Execution Engine은 바이트 코드 실행을 주로 수행한다. 필요시 기계어로 변환하기도 한다.
해당 구간에서의 핵심은 JVM은 단순히 코드를 읽는 것이 아니라, 실행 중 최적화를 수행이다.
Native Method Interface(JNI)
OS에 대하여 직접 접근이 어렵기 때문에 C/C++ 코드 호출을 가능하게 해준다.
작성자의 의문점은 다음과 같이 2개가 생겼다.
Java는 OS위에 JVM이 중간에 위치한다. 그러면 JVM은 OS에 직접 접근이 어려운가?
파일 시스템 구현, 네트워크 스택 관리, 디바이스 제어는 OS가 담당하는 것이다. 그리고 JVM은 운영체계가 아니다. JVM은 실행 환경, 메모리 관리, 추상화 역활을 수행한다. 실행 환경과 메모리 관리하는 JVM에서는 OS에 대해 직접 접근을 못 하는 것이다.
그럼 왜 C/C++ 코드 호출하는 것일까?
Java라는 언어는 의도적으로 제한된 언어이다. 그렇기 때문에 메모리 직접 접근, OS 시스템 콜 직접 호출, 하드웨어 제어를 하지 못하게 되어있다. 이러한 문제점을 해결하기 위해서 JNI를 사용하여 OS에 대한 접근이 가능한 C/C++을 호출하는 것이다.
추가적으로 JVM은 OS의 접근을 막을까? 라는 의문이 생길 수 있다.
JVM은 의도적으로 OS의 접근을 막으면서 안정성 이점을 보고 있는 것이다.
실제 백엔드 환경에서는 JVM의 동작 방식이 성능에 직접적인 영향을 준다.
예를 들어, GC가 자주 발생하면 Stop-The-World로 인해 응답 속도가 느려질 수 있고,
Heap 메모리 설정이 잘못되면 OutOfMemoryError가 발생할 수 있다.
따라서 JVM 구조를 이해하는 것은 단순한 이론이 아닌, 실제 문제 해결 능력과 직결된다.