[Java] JVM, 자바 가상 머신

Bam·2024년 2월 19일
0

Java

목록 보기
2/98
post-thumbnail

지난 포스트에서 자바를 처음 소개하면서 자바의 가장 큰 특징이라고 했던 JVM(Java Virtual Machine, 자바 가상 머신). 본격적으로 자바 프로그래밍을 시작하기 전에 자바 가상 머신에 대해서 좀 더 자세히 알고 넘어가려고 합니다.


자바 코드의 실행 과정

우리가 자바 언어를 프로그래밍 하면 .java라는 소스 코드 파일(원시 파일)이 생성됩니다. 하지만 .java파일은 컴퓨터(CPU)가 읽을 수가 없습니다.

따라서 이 원시 파일을 컴퓨터가 읽어낼 수 있도록 컴파일 과정을 거쳐야하는데, 이때 컴파일러 역할을 하는 것이 JDK를 설치할 때 함께 설치되는 자바 컴파일러입니다. 이를 통해 .java파일이 .class파일로 컴파일 되게 됩니다.

다른 언어의 컴파일러는 CPU가 바로 해석할 수 있도록 기계어 컴파일이 수행되지만, 자바 컴파일러는 JVM이 읽을 수 있는 Java bytecode(.class 파일)라는 형태로 컴파일이 되게 됩니다. 그리고 이 .class파일을 JVM이 읽어냄으로써 자바 프로그램이 실행되게 됩니다.

즉, 운영체제에 맞는 JVM이 있다면 하나의 자바 소스 코드로 어느 곳에서든 실행할 수 있게되는 것 입니다.

수동 컴파일

IDE 등을 이용하면 RUN 명령을 수행했을 때 자동으로 컴파일까지 마쳐서 수행이 됩니다. 하지만 처음이니 만큼 수동으로 컴파일하고 실행하는 방법도 알아보겠습니다.

먼저 아래와 같은 코드를 작성하고 Hello.java라는 이름을 붙여주세요.

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}

그리고 cmd를 열어서 javac Hello.java 명령을 수행해서 수동으로 컴파일해주세요. 이 결과로 Hello.class파일이 생성됩니다.

.class파일이 생성된 것을 확인했으면 java Hello 명령을 통해 실행해주세요. (뒤에 .class 확장자는 적지 않습니다.)
제대로 실행이 되었죠?


JVM의 구조

앞서본 컴파일 과정을 통해 만들어진 .class파일이 JVM을 통해 실행됩니다.

JVM은 아래 그림과 같은 구조를 갖습니다.
크게 Class Loader, Execution(실행 엔진), Runtime Data Area로 구성됩니다.

JVM의 작업 순서

.class 파일은 JVM 내부에서 다음과 같은 순서로 작업 처리가 됩니다.

  1. Runtime Data Area에서 코드 실행을 위한 메모리 할당
  2. Class Loader가 .class를 Runtime Data Area에 적재
  3. 적재 후 Execution이 Runtime Data Area의 .class를 실행
  4. Execution은 Interpreter나 JIT Compiler를 통해 기계어로 번역하고 실행

Class Loader

Class Loader.class파일을 로드, 링크, 배치하는 역할을 수행합니다.

즉, Class Loader는 클래스가 처음 실행될 때 해당 클래스를 로드하는 동적 로딩을 수행합니다.

Execution, 실행 엔진

실행 엔진은 Interpreter, JIT Compiler, Garbage Collector로 구성되어 있습니다.

Interpreter는 코드를 한 줄씩 해석하고 실행시키고, JIT Compiler는 전체 코드를 해석하고 실행한다는 차이점이 있습니다. 기본적으로는 Interpreter가 실행되다가, 자주 실행되는 .class 코드를 만나면 해당 코드는 JIT Compiler로 넘겨서 해석합니다.

또한 JIT Compiler는 같은 코드는 또 다시 전체를 해석하는 것이 아닌, 바뀐 부분만을 찾아서 컴파일하는 방식을 사용하고 있습니다.

Garbage Collector

Garbage Collector는 프로그램 메모리를 관리합니다. 자바 이전의 대표적인 언어인 C와 C++을 보면 포인터라는 개념을 통해서 프로그래머가 직접 메모리를 관리했어야했는데, 자바에서는 가비지 콜렉션을 도임함에 따라 프로그래머가 메모리를 직접 관리하지 않아도 되게 만들어졌습니다.

내부적으로 가비지 콜렉터는 JVM이 실행중일때 사용되지 않는 메모리를 계속해서 찾아내어 메모리를 비워냅니다.

Runtime Data Area

Runtime Data Area는 코드 실행에 필요한 메모리 등에 대한 정보를 담아냅니다. Runtime Data Area는 다음과 같은 5개의 영역으로 구성되어 있습니다.

  • Stack Area
  • Heap Area
  • PC Register
  • Method Area
  • Native Method Area

이 중 스택과 힙은 JVM 당 하나씩만 존재하고 PC Register, Method Area, Native Method Area는 스레드마다 하나씩 생성됩니다.

스레드(Thread)
스레드는 프로세스에서 작업을 수행하는 주체입니다.

프로세스(process)는 실행 중인 프로그램을 의미합니다.
(추후에 더 자세하게 다룰 예정이므로 지금은 이정도만!)

Stack Area

스택 영역은 주로 메소드 등에서 잠시 호출되었다가 메소드 호출 종료시 같이 사라지는 자료를 저장하기 위한 공간입니다. 호출 메소드의 매개변수, 지역변수, 리턴 값 등이 포함됩니다.

Heap Area

힙 영역은 객체, 인스턴스, 배열 등이 저장되는 공간입니다.

실제 객체는 힙 영역에 저장되고, 힙 영역에 저장된 객체를 참조하기 위한 주소값을 가진 변수 등은 스택에 저장되어있습니다.

PC Register

PC Register는 스레드가 어떤 코드(의 어떤 명령)를 실행될지에 대한 정보를 가지고 있는 공간입니다.

Method Area

Method Area는 클래스가 실행될 때 클래스의 인스턴스, 메소드 등을 저장하는 공간입니다.

위 그림에서 Runtime Constant Pool이라는 영역이 포함되어 있는데, 이 영역은 클래스 내부의 상수들을 저장하는 테이블입니다. 이 영역을 통해 상수를 참조하고 중복을 막습니다.

Native Method Stack

Native Method Stack.class 파일이 아닌, 즉 다른 언어로 작성된 프로그램을 실행시키기 위한 영역입니다.

0개의 댓글