ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JVM 구조
    Programming/Java 2022. 2. 19. 20:55

    JRE는 자바 클래스 라이브러리(Java API)와 JVM으로 구성된다.

    JVM의 역할은 자바 어플리케이션을 클래스 로더(Class Loader)를 통해 읽어 들여서 Java API와 함께 실행하는 것이다.

     

    "Write Once Run Anywhere"를 구현하기 위해 JVM은 사용자 언어인 자바와 기계어 사이의 중간 언어인 자바 바이트코드를 사용한다.

    이 자바 바이트코드가 자바 코드를 배포하는 가장 작은 단위이다.

     

    JVM은 자바 바이트코드를 실행하는 실행기이다. 

    자바 컴파일러는 C/C++ 등의 컴파일러처럼 고수준 언어 → 직접적인 CPU 명령인 기계어로 바로 변환하는 것이 아니라, 개발자가 이해하는 자바 언어 → JVM이 이해하는 자바 바이트코드로 우선 변환한다.

    자바 바이트코드는 플랫폼 의존적이지 않고, JVM이 설치된 장비라면 하드웨어나 운영체제가 다르더라도 실행이 가능하고, 컴파일된 결과물의 크기가 기존의 소스코드의 크기와 크게 다르지 않으므로 네트워크로 전송하여 실행하기 쉽다.

     

    ✔️ JVM 구조

    자바 코드 수행 과정

    JVM 내의 클래스 로더가 컴파일된 자바 바이트코드를 런타임 데이터 영역에 로드하고, 실행 엔진이 런타임 데이터 영역에 있는 자바 바이트코드를 불러와 실행한다.

     

    #️⃣ 클래스 로더

    자바는 동적 로딩, 즉 컴파일 타임이 아니라 런타임에 필요한 경우 해당 클래스를 로딩하고 링크하는 특징이 있다.

    이러한 동적 로딩을 담당하는 부분이 JVM의 클래스 로더이다.

     

    #️⃣ 런타임 데이터 영역

    런타임 데이터 영역 구성

    런타임 데이터 영역은 JVM이 OS 위에서 실행되면서 할당받는 메모리 영역이다.

    PC Register, JVM Stack, Native Method Stack은 스레드마다 하나씩 생성되고 Heap, Method Area, Runtime Constant Pool은 모든 스레드가 공유해서 사용한다.

     

    #️⃣ 실행 엔진

    클래스 로더를 통해 JVM 내의 런타임 데이터 영역에 배치된 바이트코드는 실행 엔진이 명령어 단위로 읽어서 실행한다.

    바이트코드의 각 명령어는 1Byte짜리 OpCode와 추가 피연산자로 이루어져 있으며 실행 엔진은 하나의 OpCode를 가져와 피연산자와 함께 작업을 수행한 뒤, 다음 OpCode를 수행하는 식으로 동작한다.

     

    하지만, 자바 바이트코드는 컴퓨터 기계가 바로 수행할 수 있는 언어가 아닌 비교적인 사람이 보기 편핸 형태로 기술되어 있다.

    따라서 실행 엔진은 이와 같은 바이트코드를 JVM 내부에서 컴퓨터 기계가 실행할 수 있는 형태로 변경하며, 그 방식은 2가지가 존재한다.

     

    💡 인터프리터

    바이트코드 명령어를 하나씩 읽어서 해석하고 실행한다.

    하나씩 해석하고 실행하기 때문에 바이트코드 하나하나의 해석은 빠른 대신 인터프리팅 결과의 실행은 느리다는 단점을 가지고 있다.

    바이트코드는 기본적으로 인터프리터 방식으로 동작한다.

     

    💡 JIT(Just-In-Time) 컴파일러

    인터프리터의 단점을 보완하기 위해 도입된 것이 JIT 컴파일러이다.

    인터프리터 방식으로 실행하다가 적절한 시점에 바이트코드 전체를 컴파일하여 네이티브 코드(기계어)로 변경하고, 이후에는 해당 메서드를 더 이상 인터프리팅하지 않고 네이티브 코드로 직접 실행하는 방식이다.

    네이티브 코드를 실행하는 것이 하나씩 인터프리팅하는 것보다 빠르고, 네이티브 코드는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 계속 빠르게 수행되게 된다.

     

    JIT 컴파일러가 컴파일하는 과정은 바이트코드를 하나씩 인터프리팅하는 것보다 훨씬 오래 걸리므로, 만약 한 번만 실행되는 코드라면 컴파일하지 않고 인터프리팅하는 것이 훨씬 유리하다.

    따라서, JIT 컴파일러를 사용하는 JVM들은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고, 일정 정도를 넘을 때에만 컴파일을 수행한다.

     

     

     

     

    *참고

    https://d2.naver.com/helloworld/1230

     

    'Programming > Java' 카테고리의 다른 글

    Java의 ==, equals 연산자를 통한 문자열 비교  (0) 2022.02.27
    Java 활용 포켓몬 게임  (0) 2022.01.30
    [Java] 예외(Exception)  (0) 2021.05.19

    댓글

Designed by Tistory.