자바 가상 머신(영어: Java Virtual Machine, JVM)은 자바 바이트코드를 실행할 수 있는 주체이다. 일반적으로 인터프리터나 JIT 컴파일 방식으로 다른 컴퓨터 위에서 바이트코드를 실행할 수 있도록 구현되나 jop 자바 프로세서처럼 하드웨어와 소프트웨어를 혼합해 구현하는 경우도 있다. (이론적으로는 100% 하드웨어 구현도 가능하나 비효율적이다) 자바 바이트코드는 플랫폼에 독립적이며 모든 자바 가상 머신은 자바 가상 머신 규격에 정의된 대로 자바 바이트코드를 실행한다. by wikipedia
처음 위의 문장을 읽게 된다면 무슨 소리인지 어렵게 느껴질 것이다. 하나하나 차근차근 이해해보자
일단 자바는 플랫폼에 독립적이다 라는 얘기를 많이 하게 된다. 그 말은 JVM이라는 것은 java 프로그램을 실행할 수 있는 환경을 컴퓨터에 주는 가상머신이라는 의미다.
자바 바이트 코드
0과 1으로 구성 되어 있는 이진 코드 이지만 바이너리 코드와 다르게 가상 머신(JVM)이 이해할 수 있는 코드
JVM이 왜 필요한가?
자바 프로그램은 컴파일을 하여 자바 바이트 코드를 만들어주게 되는데, 이 바이트 코드를 또 JVM을 통해서
기계어로 해석하여 실제 자바 프로그램을 실행하게 된다.
기계어는 사실 CPU의 벤더마다 다른 기계어를 가지고 있다. 예를 들면 인텔, ARM 등과 같이 다른 CPU 마다 각각의 기계어 환경을 가지고 있는 것이다. 따라서 이것을 JVM에서 인터프리팅(해석)하여 기계어로 변환해주는 역할을 하게 된다.
그럼으로 우리는 H/W의 영역을 신경쓰지 않고 다양한 CPU 환경에서 이식성에 문제 없이 Java라는 언어로 프로그래밍을 할 수있게 되는 것이다.
JVM은 크게 클래스 로더, 메모리, 실행엔진, 네이티브 메서드로 나뉘어져 있다.
클래스 로더에 의해서 메모리에 적재 되었으면 이제 인터프리터를 사용하여 바이트 코드를 변환하여 실행해야 한다.
실행엔진의 내부적으로는 인터프리터, JIT 컴파일러, GC가 있다.
인터프리터
기존의 컴파일된 .class의 바이트 코드를 한줄씩 읽어 해석하여 실행하는 역할.
한줄씩 해석하여 읽기 때문에 느리다는 평가를 받음(JIT로 보완)
JIT 컴파일러
프로그램을 실행할 때 인터프리터가 번역을 하여 사용하지만 반복적으로 나오는 코드의 경우는 매번 작업을 하는 것 보다 최초 1회 번역하여 특정 저장소에 저장하여 참조하는 방식으로 성능 향상을 이끌어 낼 수 있다.
GC
프로그램이 실행 되면 동적으로 인스턴스를 힙에 생성하게 되는데 생성된 메모리의 관리를 C++이나 C처럼 프로그래머에게 맡기지 않고 자체적으로 쓰지 않는(참조 되지 않는) 메모리를 정리하는 것이 GC이다.
java source를 컴파일 하기 위해서는 javac와 java라는 두개의 프로그램이 필요하다.
JDK(java development kit), JRE(java runtime environment)에 각각에 프로그램을 가지고 있는데 JDK가 요즘에는 JRE을 포함하고 있어 JDK를 설치하여 사용한다.
과정
1. 작성된 java source(.java)를 자바 컴파일러(javac)를 통하여 자바 바이트 코드(.class)로 변환한다
2. JVM에 있는 클래스로더에 의해 바이트코드가 JVM안으로 로드되고 실행엔진에 의해서 기계어로 해석되어 메모리에 배치된다.
3. 실행 엔진에서 바이트코드를 해석하는 경우 JIT와 인터프리터가 있는데 기본적으로 인터프리터가 한줄씩 해석하다가 적절한 시점에 JIT 컴파일러가 전체를 컴파일하고 더이상 인터프리팅하지 않고 해당 코드를 직접 실행한다.