2 minute read

★JVM(Java Virtual Machine)은 Java Application을 클래스 로더를 통해 읽어들여 실행하는 가상머신이다. Java로 작성된 프로그램이 OS에 구애받지 않도록 중재하는 중재자 역할, 메모리 관리, Garbage Collection을 수행한다. java파일을 컴파일 하여 class파일을 얻게 되는데 class파일은 기계어가 아니므로 OS를 위한 해석이 필요하다.

★모든 Application이 그러하듯 Java Application도 한정된 메모리를 사용하여 작동하고, 그 메모리를 JVM이 관리하므로 JVM의 메커니즘을 안다는 것은 Java Application의 메모리 사용 방식을 안다는 것과 같다.

★JVM의 작동 순서

  1. 프로그램이 실행되면 JVM은 OS로 부터 이 프로그램이 필요로 하는 메모리를 할당받는다.
  2. Compiler가 java파일을 class파일로 변환한다.
  3. Class Loader가 class파일을 JVM의 Runtime Data Area로 로딩한다.
  4. Execution Engine가 Runtime Data Area에 로딩된 class파일을 해석하고 실행한다.

★JVM의 구성

  1. Class Loader(클래스 로더) : 런타임 시 동적으로 JVM의 Runtime Data Area로 class파일(바이트 코드)을 로드/링크한다. 모든 클래스를 처음부터 전부 로딩하지 않고, 클래스를 처음으로 참조할 때 해당 클래스를 로드/링크한다는 의미이다.

  2. Execution Engine(실행 엔진) : Runtime Data Area에 배치된 바이트 코드를 실행시킨다. 이 때 바이트 코드를 기계가 수행할 수 있도록 두 가지 방법으로 해석한다.

방법 1. Interpreter : 자바 바이트 코드를 명령어 단위로 읽어서 실행한다. 방법 2. JIT(Just In Time) : Interpreter의 느린 수행속도를 보완하기 위해 Interpreter방식으로 실행하다 적당한 타이밍에 바이트 코드 전체를 네이티브 코드로 변경하여 캐시에 저장한다. 한번 변경된 네이티브 코드는 몇 번이든 빠르게 수행할 수 있으나 해석과정이 오래 걸리기 때문에 내부적으로 해당 메소드의 수행 빈도를 체크하여 빈도가 많을 때에만 이 방식으로 컴파일 하는 과정을 거친다.

★Garbage Collector도 이 Execution Engine에 포함되어 있다.

  1. Runtime Data Area(런타임 데이터 영역) : 프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간이다.

★Runtime Data Area의 구조

  1. Method Area : 프로그램 실행 중 어떤 클래스가 사용되면, JVM은 해당 클래스 파일을 읽어 이 곳에 정보를 저장한다. 클래스 내부의 static변수와 Method가 저장되는 공간이다. JVM당 하나의 Method Area가 있다.

  2. Heap : 클래스 인스턴스나 배열 등 객체가 저장되는 공간이다. 변수가 Call Stack에 저장되고 실제 객체가 Heap에 저장되며 Call Stack에 저장된 변수가 Heap에 저장된 객체를 가리키는 포인터의 역할을 한다. 어떤 변수도 가리키지 않는 객체(Unreachable)는 Garbage Collector에 의해 정리된다. 따라서 이 영역에는 주로 생명주기가 긴 객체들이 저장되어 있다. 또한 실행되고 있는 Thread가 몇 개이든 상관없이 Application당 하나의 Heap영역만 존재한다. Young영역, Old영역, Permanent영역으로 구성된다.

  3. Call Stack : 메소드 호출 시의 작업을 위한 메모리 공간이다. 이 공간은 메소드가 호출 될 때 할당 되며 파라메터, 지역변수와 같은 메소드 내부에서 사용하는 변수를 저장하는데 사용된다. 메소드 수행이 끝나고 }가 오면 return값을 return하고 메모리를 해제한다. 위에서 변수는 Call Stack에 저장되고 실제 객체는 Heap에 저장된다고 했으나 기본 자료형의 경우는 Call Stack에 바로 저장된다. Heap의 주소가 아니라 값이 바로 들어간다는 이야기이다. 이 영역에 있는 변수들은 가시성(scope)을 가진다. 즉 지역변수는 해당 지역이 아닌 곳에서는 접근할 수 없다. 또한 Stack메모리는 Thread별로 할당 되며 새 스레드가 생성된다면 새로운 Stack이 할당되고, 다른 스레드에서 접근할 수 없다.

  4. PC Register : Thread가 시작될 때 생성되며 현재 수행중인 JVM명령의 주소를 저장한다.

  5. Native Method Stack : Java코드가 컴파일 된 바이트 코드가 아닌 네이티브 메소드가 저장되는 공간이다. Thread별로 하나씩 존재한다.

Categories:

Updated: