Java Virtual Machine의 줄임말, 직역하면 자바를 실행하기 위한 가상 기계(컴퓨터), 또는 자바 프로그램 환경을 만들어주는 소프트웨어라고 할 수 있다.
Java는 OS에 종속적이지 않다는 특징을 가지고 있는데, OS에 종속 받지 않고 실행되기 위해선 OS 위에서 Java를 실행시킬 무언가를 필요로 하는데 바로 그게 JVM
이다.
JVM에서 Java코드 즉, 원시코드(.java
)를 실행시키기 위해 Java의 Compiler가 Java 코드를 JVM이 이해할 수 있는 바이트 코드(.class
)파일로 변환시켜준다.
변환된 바이트 코드는 기계어가 아니기 때문에 OS에서 바로 실행 시킬 수 없는데, 이 때 JVM이 OS가 바이트 코드를 이해할 수 있도록 해석해준다.
따라서, 바이트 코드는 JVM 위에서 OS에 상관없이 실행될 수 있다. OS에 종속적이지 않고, Java 파일 하나만 만들면 어느 디바이스든 JVM 위에서 실행이 가능하다.
Java 바이트 코드는 JVM이 이해할 수 있는 언어로 변환된 Java 소스코드를 의미한다. Java 컴파일러에 의해 변환된 코드의 명령어 크기가 1바이트라서 Java 바이트코드라고 불리고있다. 바이트코드는 JIT 컴파일러에 의해 바이너리 코드로 변환된다.
📢 바이너리 코드?
바이너리 코드 또는 이진 코드라고 한다. 컴퓨터가 인식할 수 있는 0과 1로 구성된 이진 코드를 의미한다.
즉, CPU가 이해하는 언어는 바이너리 코드, 가상 머신(JVM)이 이해하는 코드는 바이트 코드이다.
JVM은 바이트 코드를 명령어 단위로 읽어서 해석하는데, Interpreter방식
과 JIT 컴파일 방식
, 두 가지 방식을 혼합하여 사용한다.
기존의 자바는 Interpreter 방식으로 명령어를 하나씩 실행하게끔 이루어져 있어 실행 속도가 느렸지만, 하드웨어가 발전하면서 자바 컴파일러로 JIT 방식으로 개선되어 속도적인 측면에서 상당한 개선을 이루었다.
또한, JIT 컴파일러는 같은 코드를 매번 해석하지 않고, 실행할 때 컴파일 하면서 기계어를 캐싱해버린다. 이후에는 바뀐 부분만 컴파일하고, 나머지는 캐싱된 코드를 사용한다.
이렇게 JIT 컴파일러는 운영체제에 맞게 바이트 실행 코드로 한 번에 변환하여 실행하기 때문에 이전의 Interpreter 방식보다 성능에 10~20배 정도 더 좋다.
자바는 프로그램이 실행중인 런타임시 동적으로 클래스를 로드하고, jar 파일 내 저장된 클래스들을 JVM 위에 탑재한다. 즉, 클래스를 처음으로 참조할 때 해당 클래스를 로드하고 링크하는 역할을 하는게 클래스 로더이다.
클래스 로더는 .class
파일을 묶어서 JVM이 운영체제로부터 할당받은 메모리 영역인 Runtime Data Area로 적재한다.
클래스 로더에 의해 JVM으로 로드된 .class
파일(바이트코드)들은 Runtime Data Area의 Method Area에 배치된다.
이후 JVM은 Method Area의 바이트 코드를 실행 엔진에 제공하여, 로드된 바이트 코드를 실행하는 런타임 모듈이 실행 엔진이다.
실행 엔진은 바이트 코드를 명령어 단위로 읽어서 실행하고, 실제로 JVM 내부에서 기계가 실행할 수 있는 형태로 변경한다.
또한, 실행 엔진은 가비지 컬렉터(GC)를 포함하고 있다.
런타임 데이터 영역은 JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역이다.
PC Register
JVM Stack
Native Method Stack
Heap
Methodn Area
1. 자바로 개발된 프로그램을 실행하면 JVM은 운영체제로부터 메모리를 할당한다.
2. 자바 컴파일러(javac)가 자바 소스코드(.java
)를 자바 바이트코드(.class
)로 컴파일한다.
3. 클래스 로더를 통해 JVM 런타임 데이터 영역으로 로딩한다.
4. 런타임 데이터 영역에 로딩된 .class
들은 실행 엔진을 통해 해석한다.
5. 해석된 바이트 코드는 런타임 데이터 영역의 각 영역에 배치되어 수행하며 이 과정에서 실행 엔진에 의해 GC의 작동과 Thread 동기화가 이루어진다.
JRE는 자바 실행 환경(Java Runtime Enviroment)의 약자로 자바로 만들어진 프로그램을 실행시키는데 필요한 라이브러리들과 각종 API, 그리고 JVM이 포함되어 있다.
JRE는 자바로 개발(쓰기)은 안되고 수행(읽기)만 된다.
JDK는 자바 개발 키트(Java Development Kit)의 약자로 이름 그대로 개발자들이 자바로 개발하는데 사용된다.
JDK 안에는 개발 시 필요한 라이브러리들과 javac, javadoc 등의 개발 도구들이 포함되어 있고, 개발을 하려면 당연히 실행도 시켜줘야 하기 때문에 JRE도 함께 포함되어 있다.
📢 정리
Java로 프로그램을 직접 개발하려면 JDK가 필요하고, Java로 만들어진 프로그램을 실행시키려면 JRE가 필요하다.