siino's 개발톡

[Java] JVM이 도대체 뭐야?! 본문

Java

[Java] JVM이 도대체 뭐야?!

siino 2024. 1. 17. 17:00

Java의 특징

JVM을 알기 전에 우선 Java언어의 특성을 알아보겠습니다.

Java는 "Write Once, Run Everywhere"라는 철학으로 시작되어 발전된 프로그래밍 언어입니다. 그리고 이러한 철학을 실현하기 위해 네가지 상호 연관된 기술을 엮어 놓았습니다.

  1. The Java Programming Language
  2. The Java Class File Format
  3. The Java Application Programming Interface (Java API): Runtime 라이브러리 집합
  4. The Java Virtual Machine
기술명 주요 설명 비고
The Java Programming Language 객체지향 언어. 생산성 좋음. 


그 외에도 멀티쓰레딩, GC, Dynamic Linking, Dynamic Extension 등 많은 기술이 접목되어 있음
The Java Class File Format Java로 작성한 코드를 컴파일러를 통해 Class 파일로 재생성되는 과정을 거친다. 주요 특징 4가지 - Compact한 형태, Bytecode로의 변경, 플랫폼 독립적, 네트워크 Byte Order 사용.
The Java Application Programming Interface (Java API) Runtime 라이브러리 집합 OS 시스템과 Java 프로그램 사이를 잇는 가교(Interface) 역할.
The Java Virtual Machine 4가지 기술 중 가장 핵심. 자바 프로그램, WAS 등 자바 언어로 작성된 모든 것들을 실행.  Class 파일을 로드하여 ByteCode 해석 및 메모리, 리소스 할당하고 관리한다. JVM은 Thread 관리 및 GC와 같은 메모리 재생 작업도 수행한다.

Dynamic Linking 이란?

Dynamic Linking이라는 기술 덕분에 Class파일의 크기를 작게 유지할 수 있습니다.

Java의 Class파일은 엄밀히 말하면 실행 가능한 형태로 변경된 것이 아닌 JVM이 읽을 수 있는 형태로 번역된 것으로 이해할 수 있습니다. 이것은 JVM위에서 다시 실행 가능한 형태로 변형됩니다.

Class파일은 실행시 Link를 할 수 있도록 Symbolic Reference만을 가지고 있고, 이 Symbolic Reference는 Runtime시점에서 메모리상에서 실제로 존재하는 물리적인 주소로 대체되는 작업인 Linking이 일어나게 되는 것입니다. 이러한 Link 작업은 필요할 때 마라 동적으로 이루어지기 때문에 이를 가리켜 Dynamic Linking이라고 합니다.

 

JVM 이란?

Java Virtual Machine으로 Java가 플랫폼 독립적으로 실행할 수 있도록 만들어주는 가상 머신입니다.

*플랫폼 독립적: CPU와 OS에 의존적이지 않고 어디서나 실행될 수 있도록 하는 기술

 

위의 그림은 JVM의 구조를 나타낸 그림입니다.

 

그림을 이해해보자면

우리가 작성한 .java 파일을 javac 컴파일러를 통해 class file로 변환 후 class loader라는 모듈을 통해 JVM내부의 Runtime Data Area라는 영역에 각 데이터를 적재하고 Runtime Data area상의 적재한 데이터를 execution engine을 통해 실행시킵니다.

 

Runtime Data Area의 구성은 5가지인데 각각에 대해 알아봅시다.

Runtime Data Area의 구성요소

Method Area static 변수, 상수(runtime contant pool), class 레벨의 데이터 저장 (공통)
Heap Area 객체의 메모리가 할당된 공간
(Eden, S0, S1, Old Generation으로 나눠짐)
(공통)
Stack Area 변수, 임시데이터, 스레드 메서드 정보 저장 (스레드별 할당)
Native Method Stack 바이트코드가 아닌 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역 (스레드별 할당)
PC Register 각 스레드가 실행해야할 실행정보 저장 (스레드별 할당)

 

메모리 접근 속도

평균적으로 스택이 힙보다 빠릅니다.

스택 메모리는 최상단에 있는 요소에만 접근할 수 있으므로, 데이터의 위치를 찾는데 시간이 거의 소요되지 않는 반면 힙 메모리는 메모리 공간 전체에서 필요한 데이터의 위치를 찾아야 하기 때문에 추가적인 시간이 필요합니다.

 

Class Loader

역할: 클래스로더는 JVM이 Java어플리케이션을 실행할 때 필요한 클래스(.class파일)들을 로드하는 역할을 합니다.

 과정은 Java프로그램 실행시 필요한 클래스들을 동적으로 찾아 메모리에 올리는 것을 말합니다.

작동방식: 

- 로딩(Loading): 클래스 로더는 먼저 파일 시스템이나 네트워크 소스에서 .class파일(바이트 코드)을 찾고 JVM의 런타임 데이터 영역에 로드합니다.

- 링킹(Linking): 로드된 클래스는 검증, 준비, 분석 단계를 거쳐 사용할 준비를 합니다.

- 초기화(Initailization): 마지막으로, 클래스의 static 필드는 기본 값으로 초기화되고, static블록이 실행되어 최종 설정을 완료합니다.

 

Execution Engine

역할: Execution Engine은 로드된 클래스의 바이트코드를 실행하는 역할을 합니다.

ClassLoader가 메모리에 올린 바이트코드를 실제로 실행하는 JVM의 구성요소입니다.

작동방식:

- 인터프리터: 바이트코드를 한 줄씩 읽으면서 실행합니다. 간단하지만 느릴 수 있습니다.

- JIT 컴파일러(Just in time): 바이트코드 전체를 기계어로 컴파일하여 실행 속도를 높입니다. 이 방식은 프로그램 실행 중에 일어나며, 자주 사용되는 코드를 대상으로 합니다.

- GC: 실행엔진의 일부로, 더 이상 사용되지 않는 메모리를 자동으로 정리합니다.

 

 

-JVM의 장점

플랫폼 독립적이기 때문에 이식성이 높습니다.

-JVM의 단점

JVM을 OS위에 올려야 하므로 추가적인 메모리를 사용합니다.

 

 

참고서적 - Inside Java Virtual Machine, Bill Venners