Java Virtual Machine. 자바 프로그램을 운영체제, 하드웨어에 상관없이 실행할 수 있게 해주고, 프로그램 메모리를 관리하고 최적화해준다. 자바 바이트코드(.class)를 운영체제에 맞는 시스템 명령어로 번역하여 실행한다.
컴파일은 사람이 이해하는 언어를 기계어로 바꾸는 과정이다. 다시 말해 원시코드에서 목적 코드로 바꾸는 과정이다. 자바에서의 컴파일은 자바 소스코드(.java)를 읽어 자바 바이트코드(.class)로 변경하는 것이다.빌드란 소스코드 파일을 실행 가능하게 만들어주는 과정이다.
javac(자바 컴파일러)를 통해 컴파일한다.
$ javac 파일명.java
빌드란 소스코드 파일을 실행 가능하게 만들어주는 과정이다.
빌드 툴을 통해 실행 가능한 파일로 빌드 한 후에 실행하거나 class 파일을 직접 실행한다.
$ java 파일명
바이트코드란 가상 컴퓨터에서 작동하도록 만든 이진코드이다.
자바 바이트코드란 JVM이 이해할 수 있는 언어로 변환된 코드이며 명령어의 크기가 1 바이트라서 자바 바이트코드라고 불린다. 자바 코드를 배포하는 가장 작은 단위이고 확장자는 .class이다.
자바 바이트코드의 명령어는 OpCode와 피연산자(Operand)로 이루어져 있다.
컴파일러의 버전과 JVM 버전이 다르면 컴파일 된 바이트코드가 실행되지 않을수도 있다. 상위 버전에서 컴파일한 바이트코드는 하위 버전에서 실행하지 못한다. 하지만 컴파일 옵션으로 해결 할 수 있다.
Just In Time. 프로그램을 실제 실행하는 시점에 번역하는 컴파일 기법이다.
javac의 컴파일과 JIT의 컴파일은 다르다. 자바컴파일러(javac)는 자바 소스코드를 바이트코드로 변환하고 JIT는 변환된 바이트코드를 해석하고 실행한다.
같은 코드를 매번 해석하지 않고 실행할 때 컴파일 하면서 코드를 캐싱 한다. 사전에 정의된 임계치에서 시작하여 호출될 때마다 감소시키는 방식으로 자주 사용되는 메서드를 찾는다. 자주 사용되는 메서드는 저장해서 해석하지 않고 바로 실행시키는 방식으로 성능을 향상시킨다.
크게 Class Loader, Execution Engine, Runtime Data Area로 구성되어 있다.
클래스를 JVM의 메모리에 로드한다. 런타임 데이터 영역에 바이트코드로 배치한다.
읽어 들인 클래스를 검사한다.
클래스에 필요한 메모리를 할당하고, 클래스에서 정의된 필드, 메서드, 인터페이스들을 나타내는 데이터 구조를 준비한다.
클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경한다.
두 가지 방식을 이용하여 데이터 영역에 배치된 바이트코드를 실행한다. 데이터 영역에서 사용하지 않는 메모리를 해제한다.
프로그램 수행을 위해 OS에서 할당받은 공간
PC 레지스터, 스택, 네이티브 메서드 스택은 스레드마다 하나씩 생성되고 힙, 메서드 영역은 모든 스레드가 공유해서 사용한다.
힙(Heap)
프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 메모리 영역. New 연산자를 통해 생성한 객체, 인스턴스를 저장하는 공간으로, 가비지 컬렉션 대상이다.
메서드(Method)
클래스, 인터페이스, 필드, 메서드, Static 변수 바이트코드 등을 보관한다.
PC 레지스터(PC Register)
현재 수행 중인 JVM 명령의 주소를 갖는다. 어떤 부분을 어떤 명령으로 실행할지를 기록하며 현재 명령과 주소를 저장한다.
스택(Stack)
메서드 호출 시 생성되는 스레드 수행 정보를 기록한다. 임시 데이터를 저장한다.
네이티브 메서드 스택(Native Method Stack)
자바 외의 언어로 작성된 네이티브 코드를 위한 스택이다. JNI(Java Native Interface)를 통해 호출하는 코드를 수행하기 위한 스택이다.
JDK는 Java Development Kit의 약자로 자바 통합 개발 환경을 의미한다.
JRE는 Java Runtime Environment의 약자로 자바 실행 환경을 의미하며 JDK에 속해있다. Java9 이후로는 JDK만 배포한다.