자바 동작원리

권경환·2025년 6월 18일
0

JAVA

목록 보기
13/13
post-thumbnail

자바로 개발한 프로그램을 실행시킬때에 어떤 원리로 동작되는지를 알기위해서는 먼저 JVM 내부구조에 대해서 알아야할 필요가 있습니다.

JVM이란?

Java Virtual Machine의 약자로 자바 가상 머신이라고 불리우며
자바와 운영체제 사이에서 중개자 역할을 수행합니다.
이밖에도 아래와 같은 특징을 가지고 있습니다.
1. 자바 컴파일러가 컴파일한 Java 바이트 코드(.class)를 해석합니다.
2. 가비지 컬렉터(GC)를 사용한 메모리 관리를 자동으로 수행합니다.

JVM의 동작 방식

  1. 작성한 자바코드를 실행하면 JVM은 운영체제로부터 작성한 프로그램이 필요로 하는 메모리를 할당 받습니다.
  2. 자바 컴파일러(javac)가 자바 소스코드(.java)를 읽어서 자바 바이트코드(.class)로 변환시킵니다.
  3. Class Loader를 통해 .class 파일들을 Runtime Data Area으로 로딩한다.
  4. Runtime Data Area에 로딩된 .class 파일들은 Execution engine을 통해 해석됩니다.
  5. 이러한 과정 속에서 JVM은 필요에 따라 Execution Engine에 의해 GC(Garbage Collector)의 작동과 Thread 동기화가 이루어집니다.

JVM의 구조

1. Class Loader (클래스 로더)

클래스 로더는 JVM 내로 .class 파일들을 로드하고 링크해서 런타임 데이터 영역(Runtime Data Area)에 배치하는 역할을 합니다. 쉽게 말해, JVM이 프로그램을 실행하기 위해 필요한 클래스들을 메모리에 불러들이는 과정이라고 생각하면 됩니다.
이 과정은 크게 세 단계로 나뉩니다.

  • 1. Loading (로딩) : .class 파일을 읽어 바이트 코드를 메서드 영역에 저장하는 단계입니다.
  • 2. Linking (링크) : 로드된 클래스 파일을 실행 가능한 상태로 만드는 아래의 과정을 거칩니다.

    Verify (검증): .class 파일 형식이 유효한지, 보안에 위협이 되는 코드는 없는지 등을 검사합니다.
    Prepare (준비): 클래스 변수(static 변수)와 기본값에 해당하는 메모리를 할당합니다.
    Resolve (해결): 심볼릭 레퍼런스(예: 다른 클래스의 메서드 참조)를 실제 메모리 주소(직접적인 레퍼런스)로 교체합니다.

  • 3. Initialization (초기화) : 클래스 변수들을 실제 값으로 초기화하고, static 블록 등을 실행하는 단계입니다.

2. Runtime Data Area (런타임 데이터 영역)

런타임 데이터 영역은 JVM이 프로그램을 실행하면서 데이터를 저장하는 메모리 공간입니다. 이 영역은 여러 스레드가 공유하는 영역과 각 스레드별로 독립적인 영역으로 나뉩니다.
1. 스레드 공유 영역

  • Method Area (메서드 영역) / Non-Heap Area : 클래스, 인터페이스에 대한 런타임 상수 풀, 필드, 메서드 데이터, static 변수 등이 저장되는 공간입니다. JVM이 시작될 때 생성되며, 모든 스레드가 공유합니다.
  • Heap Area (힙 영역) : 프로그램 실행 중 생성되는 인스턴스(객체)와 배열이 저장되는 공간입니다. 메서드 영역과 마찬가지로 모든 스레드가 공유하며, GC(Garbage Collector)의 주요 대상이 되는 곳이기도 합니다.

2. 스레드 독립 영역**

  • JVM Stack : 메서드를 호출할 때마다 스택 프레임(Stack Frame)이 생성됩니다. 이 스택 프레임 안에는 메서드의 지역 변수(Local Variables), 피연산자 스택(Operand Stack), 프레임 데이터 등이 저장됩니다. 각 스레드마다 독립적으로 생성되며, 메서드 호출이 끝나면 해당 스택 프레임은 소멸됩니다.
  • PC Register : 현재 스레드가 실행될 부분의 주소와 명령을 저장하는 영역입니다. 각 스레드마다 독립적으로 존재하며, CPU가 다음에 실행할 명령의 위치를 가리킵니다.
  • Native Method Stack : 자바 코드가 아닌 C/C++ 등의 네이티브 코드(Native Code)를 호출할 때 사용되는 스택입니다. 이 역시 각 스레드마다 독립적으로 생성됩니다.

3. Execution Engine (실행 엔진)

실행 엔진은 런타임 데이터 영역에 로드된 바이트 코드를 실제로 실행하는 역할을 합니다. JVM의 두뇌라고 볼 수 있죠.

  • Interpreter : 바이트 코드를 한 줄씩 읽어서 실행합니다. 코드를 빠르게 시작할 수 있지만, 같은 코드를 여러 번 실행할 때 매번 해석해야 하므로 실행 속도가 느리다는 단점이 있습니다.

  • JIT Compiler (Just-In-Time Compiler) :인터프리터의 단점을 보완하기 위해 도입되었습니다. 자주 사용되는 바이트 코드를 미리 네이티브 코드로 컴파일하고 캐싱하여 재사용함으로써 실행 속도를 크게 향상시킵니다.

    Compilation (컴파일): 바이트 코드를 네이티브 코드로 변환합니다.
    Optimization (최적화): 컴파일된 코드를 더 효율적으로 실행할 수 있도록 최적화합니다.

  • Garbage Collector (가비지 컬렉터, GC) : 힙 영역에서 더 이상 어떤 변수도 참조하지 않는 객체들을 찾아 자동으로 메모리를 해제하여 관리합니다. 개발자가 직접 메모리를 할당하고 해제하는 번거로움을 줄여주어 메모리 누수와 같은 문제를 방지하는 데 도움을 줍니다.

profile
성장을 좋아하는 주니어 개발자의 블로그

0개의 댓글