2 분 소요

0. Overview

Purpose
  1. JVM의 정의를 알아봅니다.
  2. JVM 구조를 알아봅니다.
  3. JVM 동작 원리를 알아봅니다.

1. JVM

JVM(Java Virtual Machine)은 자바 가상 머신으로 자바 바이트 코드(.class파일)을 OS 특화된 코드로 변환하여 실행 시켜주는 가상의 머신입니다. 바이트 코드를 실행이라고 하면 바이트 코드를 인터프리터와 JIT(Just In Time) 컴파일러를 사용하여 Native OS에 맞추어 머신코드(기계어)로 변형한 다음에 최종적으론 10100 형태로 변경하여 기계가 실행 시킵니다.

JVM의 다른 정의는 바이트 코드를 실행하는 표준이자 구현체라고 표현할 수 있습니다.

  • JVM Spec(표준) : https://docs.oracle.com/javase/specs/jvms/se19/html/index.html
  • 구현 벤더 : 오라클, 아마존,..
  • JVM을 만드는 언어 : Sun사 JVM (C언어), IBM사 JVM : SmallTalk,..

VM (Virtual Machine) 이란?

  • 물리 머신 리소스를 가상화하여 생성된 격리된 가상 컴퓨팅 환경

가상화 란?

  • 하드웨어에 종속되어있는 리소스를 이용해 IT 서비스를 만드는 것

e.g. 1개의 서버를 파티셔닝 하여 2개의 운영체제를 올리고 각각의 태스크를 실행할 수 있도록 구성함.

2. Java 바이트 코드란?

자바 코드로 작성된 파일을 자바 컴파일러(javac)가 클래스 파일(.class)로 변경하고 클래스 파일 안에 있는 게 바이트 코드 입니다. 바이트 코드를 인터프리터와 JIT 컴파일러가 읽어서 머신코드(기계어)로 변경합니다.

  • 코드의 명령어의 크기가 1바이트라 바이트코드라 불림
  • JVM에서 런타임으로 해석함

3. JVM 구조

JVM 구조 (Oracle)

JVM 구조는 크게 3개의 컴포넌트로 구성되어있습니다.

  1. 클래스로더
  2. 실행엔진
  3. 메모리(Runtime Data Areas)


4. JVM 동작 원리

클래스로더

클래스(.class) 파일에서 바이트 코드를 읽고 메모리에 저장하는 일을 합니다. 3가지 과정에 의해서 동작합니다.

  1. 로딩
    클래스를 읽어오는 과정
    과정 : 부트 스트랩 클래스 로더 -> 플랫폼 클래스 로더 -> 앱 클래스 로더 순으로 클래스를 읽음

    순서 이유 ?
    Deligation Principle : 클래스 로딩할 때 기본 클래스로더 윗 방향으로 클래스로딩을 위임함
    Visibility Principle : 하위 클래스 로더는 상위 클래스가 로딩한 클래스를 볼 수 있지만, 상위 클래스 로더는 하위 클래스 로더가 로딩한 클래스를 볼수 없음.
    Uniqueness Principle : 하위 클래스 로더는 상위 클래스로더가 로딩한 클래스를 다시 로딩하지 않기 위해서 로딩된 클래스의 유일성 보장. 식별 기준은 클래스의 binary name

  2. 링크
    레퍼런스를 연결하는 과정
    과정 : Verify -> Prepare -> Resolve
    • Verify : .class 파일이 유효한지 체크
    • Prepare : static 변수, static 메소드 등 기본 값에 필요한 메모리 확보
    • resolve : 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 레퍼런스로 교체하는 일 (전체로 일어나지 않음. 일부 Optional함)
  3. 초기화
    static 변수에 값 할당



실행 엔진

실행엔진은 인터프리터, JIT(Just In Time)컴파일러, GC(Garbage Collector)로 구성 되어있습니다.

  1. 인터프리터
    바이트 코드를 한 줄씩 읽고 실행합니다. 한줄 한줄씩 컴파일하여 native code로 변환 실행합니다.

  2. JIT(Just In Time) 컴파일러
    인터프리터의 효율을 높이기 위해 바이트 코드의 반복되는 코드를 발견하면 미리 네이티브 코드로 바꾸어 실행합니다.

  3. GC (Garbage Collector)
    더이상 참조되지 않은 객체를 모아서 정리합니다.



메모리 (Runtime Data Area)

메모리는 총 5개 영역으로 구성되어있습니다.
메소드 영역(method)영역, 힙(heap)영역은 공유 자원으로 다른 영역에서도 공유가 가능합니다.
스택(stack), PC(PC register), 네이티브 메소드 스택은 쓰레드에 국한되어 쓰레드 내에서만 공유합니다.

  1. 메소드(method) 영역
    클래스 수준의 정보(클래스 이름, 부모클래스 이름, 메소드, 변수)를 저장합니다.

  2. 힙(heap) 영역
    객체 생성 시 저장합니다. GC의 대상이 됩니다.

  3. 스택(stack)
    쓰레드 마다 런타임 스택을 생성하고 그 안에 스택 프레임을 쌓습니다. (스택 프레임 = method call)

  4. PC(Program Counter)register
    쓰레드 마다 쓰레드 내 현재 실행할 instruction위치를 가르키는 포인터가 생성됩니다. 쓰레드가 실행될 때마다 어느 위치를 실행하고 있는 지 알려줍니다.

  5. 네이티브 메소드 스택
    네이티브 메소드 라이브러리를 사용하려면 JNI를 통해서 사용하고 사용하기 위한 스택을 생성합니다.



5. Conclusion

JVM의 정의와 구조, 동작 원리를 살펴보았습니다. 다음은 바이트 코드가 실행 되면서 메모리에 저장되는 구조를 살펴볼 예정입니다.

References

(인프런) 더 자바, 코드를 조작하는 다양한 방법 - 백기선

카테고리: ,

업데이트: