JVM은 'Java virtual machine'을 줄인 말로 '자바를 실행하기 위한 가상 머신' 즉 '가상 컴퓨터'라고 할 수 있다.
'가상 컴퓨터'는 실제 하드웨어가 아닌 소프트웨어로 구현된 컴퓨터라는 뜻으로 컴퓨터 속의 컴퓨터라고 할 수 있다.
자바로 작성된 애플리케이션은 이 가상 컴퓨터(JVM)에서만 실행되기 때문에, 자바 애플리케이션이 실행되기 위해서는 반드시 JVM이 필요하다.
위의 그림에서 처럼 C언어 같은 경우 OS만 거치고 하드웨어로 바로 전달되는 것에 반해 JAVA는 JVM을 한번 더 거치는 것을 볼 수 있다.
그리고 하드웨어에 맞게 완전히 컴파일된 상태가 아니고 실행 시 해석(interpret)되기 때문에 속도가 느리다는 단점을 가지고 있다.
그러나 요즘엔 바이트코드(컴파일된 자바코드)를 하드웨어의 기계어로 바로 변환해주는 JIT컴파일러와 향상된 최적화 기술이 적용되어서 속도의 격차를 많이 줄였다.
두 번째 위의 그림은 자바가 OS에 독립적인 특징을 갖고 있다는 것을 보여주는 그림이다.
일반 애플리케이션은 OS와 바로 맞닿아 있기 때문에 OS에서 실행시키기 위해서는 애플리케이션을 그 OS에 맞게 변경해야한다. 즉 OS 종속적이라는 단점을 가지고 있다.
하지만 자바의 경우 애플리케이션과 OS의 중간 단계에서 소통하는 JVM이 있기 때문에 다른 OS에서도 현재 OS맞는 JVM을 다운로드 한다면 프로그램의 변경없이 실행이 가능하다. 즉 OS에 독립적인 장점을 가지고 있다.
요약하면 JVM이란 '가상 머신'으로 내부적인 복잡한 구조로 자바애플리케이션을 실행하는 주체라고 할 수 있다.
자바에서의 전체적인 실행과정은 아래의 이미지와 같다.
이제부터 JVM의 구체적인 실행과정을 알아보자.
우선 소스파일을 작성하고 저장하게되면 Java Compiler에 의해 .java의 소스파일이 JVM이 이해 할 수 있는 바이트코드(Bytecode)로 이루어진 .class파일로 저장된다.
바이트코드로 작성된 class파일을 JVM내로 로드하는 역할을 하고, 이렇게 로딩된 class들은 Runtime Data Area배치된다. (이러한 로드과정은 운영체제가 담당한다)
Class Loader에 의해 메모리에 적재된 클래스의 Bytecode들을 BinaryCode 즉 기계어로 변경하고 명령어 단위로 실행한다.
명령어의 실행은 위에서 언급한바와 같이 인터프리터(Interpreter)방식 또는 JIT(Just-In-Time)컴파일러 방식이 있다. JIT 방식의 경우 바이트코드를 기계어로 변환하기 때문에 빠르다는 장점이 있지만 비용이 발생한다는 단점이 있다.
인터프리트 방식은 실행 중 프로그래밍 언어를 읽어가면서 해당 기능에 대응하는 기계어 코드를 실행하기 때문에 느리다는 단점이 있다.
Garbage Collector(GC)는 Heap 메모리 영역에 생성(적재)된 객체들 중에 참조되지 않는 객체들을 탐색 후 제거하는 역할을 한다.
GC가 역할을 하는 시간은 정확히 언제인지 알 수 없다.
JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역이다.
이 영역은 크게 아래와 같이 나뉜다.
JVM 구조와 자바 런타임 메모리 구조
자바의 정석 기초
[Java] JVM 메모리 구조
[18] 자바 메모리 구조