본문 바로가기

IT/Dev

03. JVM (Java Virtual Machine)

01. JVM이란?

JVM(Java Virtual Machine)은 자바 가상 머신을 칭하는 말이다. JAVA와 OS사이의 중재자 역할로 다양한 OS환경 위에서 JAVA를 수행할 수 있도록 한다. JAVA Applcation을 클래스 로더로 읽어들여 자바 API와 함께 실행하는 역할로, 운영체제에 독립된 플랫폼을 갖게 한다.

 

02. JVM 수행과정

  1. 프로그램이 수행되면, JVM은 OS로부터 메모리를 프로그램이 필요로하는 메모리를 할당받는다. JVM에서는 할당받은 메모리를 영역별로 분배하여 관리한다.
  2. 자바 컴파일러(javac)가 자바소스(.java)를 읽고 바이트코드(.class)로 변환 한다.
  3. 변경된 Class파일을 Class Loader를 통해 JVM Runtime영역(Runtime Data Area)으로 로딩한다.
  4. 로딩된 Class파일을 실행엔진(Excution Engine)에서 실행한다.

 

 

03. JVM

  • Java Compiler는 Java 소스(.java)를 컴파일 하여 바이트 코드를 만들고, 이를 .class에 저장하는 역할을 한다.
  • Class Loader는 Class Loader는 저장된 .class파일들을 읽어와 운영체제로부터 할당받는 메모리 공간인 Runtime Data Areas에 적재하는 역할을 한다. 이러한 역할은 자바 어플리케이션이 실행 될 때만 수행된다.
  • Execution Engine(실행 엔진)은 Class Loader에 의해 Runtime Data Areas에 적재된 바이트 코드화 된 클래스들을 기계어로 변경해 명령어 단위로 실행하는 역할을 한다. Execution Engine(실행 엔진)은 바이트코드를 명령어 단위 별로 읽어와서 실행한다. 하지만 인터프리터의 단점을 그대로 가지고 있기 때문에 한 줄 씩 수행하고, 그 때문에 속도가 느리다는 단점을 가지고 있다. JIT compiler는 이러한 인터프리터의 단점을 고치기 위해서 도입된 컴파일러이다. 적절한 시간에 전체 바이트 코드를 네이티브 코드로 변경해서 Execution Engine이 네이티브로 컴파일된 코드를 실행하는 방식으로 되어 성능을 높일 수 있다.
  • Runtime Data Area는 JVM에서 메모리에 존재하는 영역으로 자바 어플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역이다. Runtime Area에는 Method, Heap, Java stack, PC Register, Native method stack의 5가지 영역으로 나누어 진다.
  • Method Area에서는 클래스와 인터페이스에 존재한 상수 풀 및 멤버 변수, 클래스 변수(Static 변수), 생성자 및 메소드를 저장하는 공간이다.

  • Heap영역은 JVM에서 런타임시 동적으로 할당하여 사용하는 영역으로서 New 연산자로 생성된 객체 또는 객체와 배열을 저장한다. 또한 참조하는 변수, 필드가 없다면 제거 대상이 되는 객체로 GC의 대상이 된다. 여기서 Young Generation과 Old Generation 영역은 자바 어플리케이션 단에서 사용하는 부분이다. 기존에는 Permanent 영역이 존재하였지만 JAVA8 이후로는 이 부분이 사라지고 Native 영역에 Metaspace 영역이 생겼다.

  • Stack Area는 쓰레드 마다 스택이 하나 씩 존재하며, 스레드가 시작 될 때 할당된다. 선입 후출(LIFO) 구조로 push, pop 기능을 사용한다. 원시타입(Primitive type) 변수는 스택 영역에 직접적인 값을 가진다.

  • PC Register는 현재 수행 중인 JVM의 명령 주소를 갖는 부분으로 메모리에 데이터 전달 전에 저장 한다.

  • Native Method Stack는 Java가 아닌 언어로 작성된 네이티브 코드들을 저장하기 위한 Stack이다. JNI, JNA 모두 이 부분을 이용하여 C/C++ 코드를 수행하기 위해 필요하다. 또한 네이티브 메소드의 매개변수, 지역변수 등을 바이트 코드로 저장한다.