본문 바로가기

Java/JVM

[JVM] JVM 이란?

이번 장에서는 JVM이 무엇이고 어떤 역할을 하는지 알아보도록 한다.
현재 진행 중인 프로젝트의 JVM을 튜닝하고 GC를 선택하는 과정에서 JVM에 대한 지식이 많이 부족하다는 것을 느껴서 자료들을 정리하는 시간을 가져본다.


JVM (Java Virtual Machine) 이란?

위키백과에 따르면 JVM을 아래와 같이 정의하고 있다.

자바 가상 머신은 자바 바이트 코드를 실행할 수 있는 주체이다.
일반적으로 인터프리터나 JIT컴파일 방식으로 다른 컴퓨터 위에서 바이트 코드를 실행할 수 있도록 구현되나
jop자바 프로세서처럼 하드웨어와 소프트웨어를 혼합해 구현하는 경우도 있다.
자바 바이트 코드는 플랫폼에 독립적이며 모든 자바 가상 머신은 자바 가상 머신 규격에 정의된 대로 자바 바이트코드를 실행한다.
따라서 표준 자바 API까지 동일한 동작을 하도록 구현한 상태에서는 이론적으로 모든 자바 프로그램은 CPU나 운영 체제의 종류와 무관하게 동일하게 동작할 것을 보장한다.

어려운 말들이 많이 나왔는데 JVM이 존재하는 가장 중요한 이유는 자바 프로그램은 CPU나 운영 체제의 종류와 무관하게 동일하게 동작한다이다.
VM (Virtual Machine)이 생소할 수 있으므로 조금 더 직관적인 가상머신 두 개만 예를 들어본다.
아래의 NoxPlayer는 PC에 설치되어 모바일 게임을 즐길 수 있게 해주는 VM이다.
모바일 게임 자체가 모바일 환경을 대상으로 개발되었기 때문에 VM 없이 PC에서 실행되는 것은 불가능하다.

다음으로 VMWare를 설치하고 원하는 OS를 설치하는 경우 사용자가 원하는 OS환경을 사용가능하다.
필자의 경우 Linux를 사용하기 위해서 Window PC에 VMWare를 설치하고 centOS를 설치하여 사용하였다.

VM의 가장 큰 특징은 어떠한 환경에서도 실행이 가능하다는 점이다.
이러한 이유를 개발자들은 환경별로 처리하는 시간을 소비하는 대신 자신이 개발하는 서비스 로직에 더 집중이 가능하다.

JVM 작동 원리

  • 프로그램이 실행되면 JVM은 OS로부터 메모리를 할당받는다.
    이때 할당 받은 메모리를 크게 Class Loader, Runtime Data Areas, Excution Engine 으로 나누어 관리한다.
  • Java Compiler (javac)는 우리가 작성한 .java 파일을 java byte code (.class)로 변환시킨다.
  • java byte code는 OS가 해석할 수 없다. 이때 Class Loader가 .class 파일을 JVM에 적재한다.
  • 적재된 파일을 Execution Engine이 해석하게되고 Runtime Data Area에 적재되어 실행된다.

JVM 구조

Class Loader

Java 소스 코드는 Javac 컴파일러를 거쳐 바이트코드로 변환되고 JRE(Java Runtime Environment)에 들어있는 java class loader에 의해 JVM으로 적재된다.

Execution Engine

JVM에 적재된 바이트 코드를 실행하는 Engine.
Runtime Data Areas에 적재된 바이트 코드는 Execution Engine에 의해 실행된다.
초창기 JVM은 인터프리터(Interpreter)방식이었다. 인터프리터 방식의 경우 코드를 한 줄씩 내려가면서 실행하는 프로그램이기 때문에 컴파일러 언어에 비해서 성능이 낮다는 이슈가 있었다. (대부분의 고급 프로그래밍 언어는 인터프리터 언어이며 대표적으로 python과 javascript가 있다.)
이러한 성능이 낮은 문제를 해결하기 위해 JIT 컴파일러를 인터프리터에 내장하였다.
JIT(just-in-time) 컴파일의 경우 C나 C++처럼 실행하기 전에 처음 한번 컴파일하는 대신, 프로그램을 실행하는 시점에서 필요한 부분을 즉석으로 컴파일 하는 방식이다.

Runtime Data Area

Runtime Data Area는 총 5가지로 구분되며 좌측 3개의 영역은 Thread별로 생성되며 우측 2개의 영역은 모든 Thread가 공유한다.

PC Register (Thread마다 존재)
현재 수행 중인 JVM Instruction의 주소를 가지게 된다.
프로그램의 실행은 CPU에서 instruction을 수행하는 과정으로 이루어지고 CPU는 이러한 instruction을 수행하는 동안 필요한 정보를 Register에 저장한다. CPU의 경우 Register - Base로 작동하지만 PC Register는 Stack - Base로 작동한다.

JVM stack (Thread마다 존재)
Thread의 수행 정보를 Frame을 통해서 저장한다. Method가 호출되면 Method와 Method정보는 Stack에 쌓이게 되며 Method 호출이 종료 될때
Stack point에서 제거된다. Method 정보는 해당 Method의 매개변수, 지역변수, 임시변수등을 저장하고 Method 종료 시 메모리 공간이 사라진다.

Native Method stack (Thread마다 존재)
Java 이외의 언어로 작성된 네이티브 코드들을 위한 Stack이며 JNI(Java Native Interface)를 통해 호출되는 C/C++등의 코드를 수행하기 위한 Stack.
커널이 스택을 통해 독립적으로 프로그램을 실행시키는 영역.

Method Area (모든 Thread가 공유, Class Area & Static Area라고도 한다.)
Class Loader가 메모리에 적재할 때 초기화되는 대상을 저장하기 위한 메모리 공간. 자바는 Main 메소드의 호출부터 계속 메소드의 호출로 흐름을 이어가기 때문에 메소드의 바이트코드는 프로그램의 흐름을 구성하는 바이트코드로 구성되어 있다.
클래스, 인터페이스, 메소드, 필드, Static 변수등의 바이트 코드를 보관한다.
Runtime Constant Pool이라는 영역도 존재하며 상수 자료형을 저장하여 참조하고 중복을 막는 역할을 수행한다.

Method Area에 적재되는 데이터는 아래와 같다.

  • Field Information
    멤버변수의 이름, 데이터 타입, 접근 제어자 정보
  • Method Information
    메소드의 이름, 리턴타입, 매개변수, 접근제어자에 대한 정보
  • Type Information
    class & interface 여부, class & interface 이름, class의 경우 부모 클래스의 이름
    Method Area의 경우도 Garbage Collection의 대상이 된다.
    (Hotsopt JVM(Oracle)은 Method Area를 Permanent Area(PermGen)이라고 부른다.)

Heap (모든 Thread가 공유)
프로그램에서 런타임 시 동적으로 할당하여 사용하는 영역.
클래스를 사용하여 instance를 생성하면 Heap 영역에 저장된다.
Method Area는 클래스 데이터를 위한 공간이고 Heap은 객체를 위한 공간이다.
Heap의 자세한 내용은 다음 장에서 다루도록 한다.
Garbage Collection의 대상이 되는 영역이다.

참고 자료

'Java > JVM' 카테고리의 다른 글

[JVM] GC 벤치마크 결과  (0) 2022.01.23
[JVM] GC 벤치마크 분석 포인트  (0) 2022.01.23
[JVM] GC 벤치마크 개요  (0) 2021.12.23
[JVM] GC 알고리즘 종류  (0) 2021.12.02
[JVM] Heap & GC  (0) 2021.12.02