본문 바로가기

Development/Java

JVM

JVM이란?


JVM(Java Virtual Machine)은 bytecode를 실행하기 위해 필요한 가상머신이다.

bytecode는 사용자가 작성한 순수한 Java source file이 아닌, 컴파일러에 의해 컴파일된 파일을 의미하며, JVM은 컴파일된 bytecode를 운영체제에 알맞은 기계어로 번역하여 실행가능하게 만든다.

즉, OS가 달라도 Java실행에 필요한 컴파일러와 JVM이 있다면 실행가능하다는 말이며 OS에 종속적이지 않다는 말이 된다. 다르게 말하면 JVM에 종속적인 특징을 가진다고도 할 수 있다.

 

JVM의 구성요소


사진 출처 : https://ko.wikipedia.org/wiki/자바_가상_머신#/media/파일:JvmSpec7.png

실행과정을 매우 간소화해보자면, 클래스로더가 바이트코드를 메모리에 적재하고 Execution Engine을 통해 실행하며, 실행 방식은 인터프리터 방식과 JIT 컴파일러 방식을 사용한다.

 

 

Class Loader

bytecode를 JVM에 적재하는 역할을 한다. 실행에 관련된 클래스 파일들을 모두 할당받은 메모리 영역에 로드한다.

할당받은 메모리에 위의 JVM Memory 공간에 맞게 적절하게 배치한다.

이 작업은 Runtime 환경에서 이루어진다.

JVM Memory

  • 이 공간은 데이터가 저장되는 공간으로, 어떤 데이터들이 어떤 곳에 저장되는지 서술한다.

Method Area

  • 클래스 데이터, 인터페이스, 메소드, Contant Pool, static 변수 등을 포함한다.
  • Thread들이 공유하는 데이터
  • JVM의 시작부터 종료시점까지 유지된다.

Heap

  • 인스턴스 저장하는 공간
  • 런타임 시점에 동적으로 메모리에 할당한다.
  • Thread들이 공유하는 데이터
  • Heap 메모리에서 더이상 참조되지 않는 객체는 GC의 대상이 된다.

Stack

  • Thread 별로 할당
  • Frame단위로 Stack에 쌓이며, 결과가 반환되면 제거(Stack의 특징과 같음)
    • Frame은 Local Variable, Operand Stack, Constant Pool Reference로 구성
      • Local Variable : 실행 메서드의 지역변수
      • Operand Stack : 메소드 내의 연산을 위해 필요한 공간
      • Constant Pool Reference : Constant Pool 참조를 위한 공간
    • 예를들어, 함수를 호출할 때 Call by Value를 예로 들 수 있수 있는데, 함수를 인자로 넘겨주어 해당 인자를 변경해도 호출 메서드에 존재하는 지역변수는 변경되지 않는다.
    • Frame에 대한 실행이 끝나면 제거되면서 결과 값을 호출한 메서드에게 반환하게 된다.

Native Method Stacks

  • Java로 작성되지 않은 메소드를 다루는 영역
    • Native Method란, 순수 Java code로 사용할 수 없는 기능을 위해 다른 프로그래밍 언어로 작성된 메소드를 의미한다.
  • Thread 별로 할당

PC(program Counter) Registers

  • Thread 별로 할당
  • Thread는 동시에 서로 번갈아가며 실행되어야 하기 때문에 실행되는 부분의 주소와 명령을 저장할 공간이 필요한데 이것의 역할을 해주는 것이 PC Register이다.

Execution Engine

Java 실행에 필요한 데이터가 메모리에 로드가 되었다면 Execution Engine을 통해 실행한다.

이 과정에서 bytecode를 다시 기계어로 번역하게 되는데, 위에서 설명한 2가지 방식을 사용한다.

Interpreter

bytecode의 명령어를 한 줄씩 실행하는 방식으로, 실행속도가 느린 단점이 있다.

JIT(Just-In-Time) Compiler

기본적으로 Interpreter방식을 사용하지만 속도가 느린 단점을 보안하기 위해 JIT Compiler를 사용한다.

프로그램 실행 시점에 컴파일하여 각 OS에 맞는 Native Code로 변환하고, 해당 코드를 캐싱하여 사용한다. 후에 변경되는 부분이 있다면 그 부분만 컴파일하는 방식으로 낭비를 줄이고 속도를 높혔다.

메인은 Interpreter로 사용하며 반복되지 않는 부분을 컴파일러를 사용하는 것으로 단점을 보완하였다.

 

 

 

Reference

JVM에 관하여 - Part 3, Run-Time Data Area

자바 가상 머신 - 위키백과, 우리 모두의 백과사전

JVM 구조와 자바 런타임 메모리 구조 (자바 애플리케이션이 실행될 때 JVM에서 일어나는 일, 과정을 설명해줄 수 있나요?)

[Java-Live-Study] 1주차 - 자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해