[JAVA] JVM(Java Virtual Machine)이란?
JVM(Java Virtual Machine)이란?
JVM은 Java Virtual Machine, 즉 자바 가상 머신의 약자를 따서 줄여 부르는 용어이다. JVM은 OS와 Java 애플리케이션 사이의 중개자 역할을 한다. JVM은 자바 바이트코드를 실행할 수 있는 환경을 제공해준다. 이를 통해 자바 바이트 코드가 플랫폼에 독립적으로 어디서든 실행될 수 있게 한다. 즉, JVM 덕분에 OS에 상관없이 어디서든 JAVA 애플리케이션을 실행할 수 있게 된다.
JVM 구성
1. Class Loader(클래스 로더)
JVM내로 클래스파일(.class)를 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈이다. Runtime 시점에 클래스를 로딩하게 해 주며 클래스의 인스턴스를 생성하면 클래스 로더를 통해 메모리에 로드하게 된다.
2. Execution Engine(실행 엔진)
로드된 클래스의 바이트코드를 실행하는 런타임 모듈이 바로 실행 엔진이다. 클래스 로더를 통해 JVM내의 Runtime Data Areas에 배치된 바이트코드는 실행 엔진에 의해 실행되며, 실행 엔진은 자바 바이트 코드를 명령어 단위로 읽어서 실행한다. 여기서 Interpreter(인터프리터) 방식과 JIT compiler 방식을 사용하게 된다.
3. Interpreter(인터프리터)
인터프리터는 프로그래밍 언어의 소스 코드를 바로 실행하는 프로그램을 말한다. 원시 코드를 기계어로 번역하는 컴파일러와 대비된다. 자바는 인터프리터 방식을 사용하여 자바 바이트 코드를 명령어 단위로 읽어서 실행한다. 하지만 한 줄씩 수행하기 때문에 수행 속도가 느리다는 단점이 있다.
인터프리터와 컴파일러의 차이점에 대해 자세히 알고 싶다면 다음을 참고하자!
4. JIT Compiler (Just In Time Compiler)
인터프리터 방식의 단점을 보완하기 위해 JIT 컴파일러가 도입되었다. JIT 컴파일러는 바이트코드를 컴파일하여 native code(네이티브 코드)로 변환하여 사용한다. 즉 한 번 컴파일된 코드는 빠르게 수행하게 되어 수행 속도가 빠르게 된다. 하지만 컴파일하는 과정에 비용이 들게 된다. 따라서 한 번만 수행할 코드라면 컴파일하지 않고 인터프리팅 하는 것이 유리하다. 따라서 JVM은 인터프리터 방식을 사용하다가 일정한 기준이 넘어가면 JIT 컴파일러를 사용하는 혼합 방식을 사용한다.
5. Garbage Collector(가비지 컬렉터)
가비지 컬렉터는 유효하지 않은 메모리인 가비지(Garbage)를 정리해주는 역할을 한다. 즉 Garbage Collection(GC)를 담당한다. GC의 과정 등 더 자세한 내용은 다음을 참고하자. 중요한 내용이다!
6. Runtime Data Area
Runtime Data Area는 JVM이 프로그램을 수행하기 위해 OS로부터 별도로 할당받은 메모리 공간을 말한다. Runtime Data Area는 크게 5가지 영역으로 나눌 수 있다.
1) PC Register
JVM의 PC Register는 CPU 내의 기억장치인 레지스터와 다르게 작동한다. PC Register는 각 쓰레드 별로 하나씩 존재하며 현재 수행 중인 JVM Instruction의 주소를 가지게 된다. 즉, 스레드가 어떤 명령을 실행할지 기록하는 부분이라고 할 수 있다.
2) JVM Stack
메소드(method)가 호출될 때 메서드와 메서드의 정보는 JVM Stack에 쌓이게 된다. 즉, 메서드의 매개변수(parameter), 지역 변수(local variable), return 주소, 임시 변수 등의 정보를 기록하는 스택이다. 각 스레드 별로 생성되기 때문에 다른 스레드는 접근할 수 없다. 메서드 호출이 종료되면 스택에서 정보들이 제거된다.
3) Native Method Stack
자바 외의 언어로 작성된 네이티브 코드들을 위한 스택이다. Java Native Interface를 통해 호출되는 C/C++ 등의 코드를 수행한다.
4) Method Area
모든 쓰레드가 공유하는 메모리 영역으로 클래스, 인터페이스, 메서드, 필드, Static 변수 등의 바이트 코드를 보관한다. Method Area에는 Runtime Constant Pool이라는 별도의 관리 영역도 존재한다. 이는 상수 자료형을 저장하고 참조하여 중복을 막는 역할을 수행한다.
5) Heap
Runtime 시점에 동적으로 할당하여 사용하는 영역이다. 클래스를 이용해 인스턴스를 생성하면 Heap에 저장된다. 즉, new연산자를 이용해 생성된 객체를 저장하는 영역이다. Heap은 크게 New/Young 영역, Old 영역, Permanent Generation 3 영역으로 나뉜다. 참고로 java8 이후에는 Permanent 영역이 Metaspace 영역으로 바뀌었다.