본문 바로가기

Java

JVM (Java Virtual Machine)과 메모리 영역

JVM(Java Virtual Machine)

  • JDK, JRE, JVM 등이 무어인지 명확히 정의하지 못할 때가 많다.
    • JDK란 java development kit의 약자로 JRE + Development Kit(개발을 위한 도구) 이라고 쉽게 생각하면 된다.
    • JRE란 Java Runtime Environment의 약자이다. 그리고 이 JRE는 JVM + libraries 이라고 생각하면 된다.
  • JVM은 Java Virtual Machine 선 마이크로 시스템즈에서 개발했다. 원래의 목적은 가전 제품들에 사용하는 코드를 어떠한 운영체제를 사용하더라도 돌아가게 만드는게 목적이었다.
    • 그 목적을 이루기위해서는 운영체제 위에 virtual machine을 두어서 이 가상 머신이 동일한 코드를 넣으면 각 운영체제에 맞게 기계어로 변환을 해주는 역할을 한다.

JVM 이란?

  • JVM이란 Java Virtual Machine 의 약자로 말 그대로 자바를 실행하는 가상 머신이다. 가상 머신이란 특정 프로그램을 실행하기 위한 하드웨어를 소프트웨어로 구현한 것을 의미한다. 이 의미를 가져와서 생각해보면 자바 가상머신은 자바를 실행하기위한 하드웨어를 소프트웨어로 만들어놓은 것이라 볼 수 있다.
  • 좀 더 JVM의 기능에 초점을 맞추어 설명을 해보면 Java 프로그램과 OS(운영체제) 사이에서 중개하여 실행하는 프로그램으로서 Java가 어떠한 운영체제에서도 실행할 수 있도록 만들어주는 프로그램이다.
    • JVM은 Java compiler를 통해 만들어진 Java Bytes Code(.class 파일)를 해석하고 실행하는 역할을 한다.

왜 JVM을 알아야하는가?

  • 보통 JVM을 안다 라고 하는것은 JVM의 메모리구조를 안다라고 생각하는 경우가 많은 것 같다.
  • 메모리 구조를 왜 알아야할까?
    • 그 이유는 내가 개발한 프로그램이 한정된 메모리에서 최대의 효율을 낼 수 있어야 하기 때문이다.
    • 메모리가 부족한지, 그 메모리를 어떻게 관리하는 지 에 따라 프로그램의 성능이 달라질 수 있기 때문이다.

자바 프로그램의 실행 과정

  1. 프로그램이 실행되면 JVM은 OS로부터 이 프로그램이 필요로 하는 메모리를 할당 받는다.
  2. 자바 컴파일러(javac)가 소스코드(.java)를 읽어들여서 자바 바이트 코드(.class)로 변환시킨다.
  3. Class Loader는 자바 바이트 코드를 JVM으로 로딩한다.
  4. class 파일은 Execution Engine을 통해 해석된다.
  5. Class Loader는 다시 해석된 코드를 Runtime Data Area에 배치된다.

  • JVM은 크게 Class Loader, Execution Engine, Runtime Data Area로 구성된다.Class Loader
  • 말 그대로 자바 바이트 코드(클래스 파일)들을 JVM으로 로딩하는 역할을 수행한다.
  • 자바는 런타임 시에 동적으로 클래스를 런타임 데이터 영역에 로드하고 링킹한다. (해당 클래스가 처음 사용 될 때!)
  • 메모리에서 사용하지 않는 클래스들은 삭제한다.

Execution Engine (실행 엔진)

  • 실행엔진은 Class Loader에 의해 런타임 데이터 영역에 배치된 Byte Code를 해석하고 이를 기계가 실행할 수 있는 언어로 변경하고 실행하는 역할을 한다.
  • 실행엔진은 두 가지 종류가 있다.
  • Interpreter
    • 자바 바이트 코드를 명령어 단위로 읽어들여서 실행한다.
    • (인터프리터 언어의 단점)이 때문에 느리다.
  • JIT
    • Just In Time 컴파일러로 인터프리터 방식의 단점을 보완하기위해 나왔다.
    • 처음에 JVM은 인터프리터 방식으로 읽으면서 실행하다가 적절한 시점에 바이트코드 전체를 컴파일하여 네이티브 코드로 변경하고, 이후에는 더 이상 인터프리팅 하지 않고 네이티브 코드로 직접 실행한다.
    • 네이티브 코드는 캐시에 보관되기 때문에 컴파일된 코드를 빠르게 실행한다.
    • JIT 컴파일러가 컴파일을 수행하는 과정은 인터프리팅하는 과정보다 훨씬 오래 걸리므로 한번만 수행할 메서드는 인터프리팅 방식으로 수행하는게 낫다.
    • JVM은 내부적으로 프로그램의 메서드가 얼마나 수행되는지를 모니터링 하다가 적절한 시점에 컴파일을 수행한다.

Runtime Data Area

  • PC Register, JVM Stack, Native Method Stack은 각각의 쓰레드별로 부여되는 메모리 공간이고 Heap과 Method Area는 모든 쓰레드가 공유하여 사용하는 메모리 영역이다.
  1. PC 레지스터
    • 각 쓰레드별로 실행하는 명령어의 주소값을 갖고있는 공간이다.
  2. JVM stack
    • 각 쓰레드의 로컬 변수나 객체의 주소값, 함수의 콜스택 등이 저장되는 공간이다.
  3. Native Method stack
    • 자바에서는 Native Method 라고 불리는 다른 언어로 작성된(주로 C언어) 함수들이 호출되기도 한다. 이 함수들이 호출될 때 쌓이는 스택을 Native Method Stack이라 하고 이 영역도 각 쓰레드 별로 할당된다.
  4. Method Area
    • JVM에서는 클래스의 구조나 정보, 생성자, 필드에 대한 정보가 저장된다. static 변수 등도 이 곳에 저장된다.
  5. Heap
    • 객체의 인스턴스, 배열들이 저장되는 공간으로 GC가 처리하는 메모리 영역이다.