JVM(Java Virtual Machine) 기능 및 동작

dO_the_Jeegu·2023년 1월 12일
1

코드스쿼드 CS16

목록 보기
3/3

1. JVM(Java Virtual Machine) 자바 가상 머신

    : 자바 프로그램은 완전한 기계어가 아닌 중간 단계의 바이트코드(Bytecode)다. 따라서 운영체제가 자바 프로그램을 실행하기 위해선 바이트코드를 해석하고 실행할 수 있는 일종의 번역기가 필요한데 그것이 바로 JVM이다.

✋ 바이트코드란?
   : 바이트코드는 어떤 플랫폼 및 운영체제에 독립적으로 실행될 수 있는 가상기계용 기계어 코드다. 따라서 JVM만 설치되어 있으면 어떤 운영체제라도 각 운영체제에 맞는 실행 파일로 변환하여 실행할 수 있다.


2. JVM 동작 및 구성 요소

이미지 출처

(1) 클래스 로더(Class Loader)
   : 클래스 파일을 메모리에 적재하는 기능. 자바 프로그램을 실행하기 위해 바이트코드로 이루어진 클래스 파일(.class)을 JVM으로 로딩시키고, JVM은 바이트코드를 해석하여 실행 가능한 상태로 만든다.

✍ 바이트코드 검증 도구(Bytecode Verifier)
  : 클래스파일이 클래스로더에 의해 메모리에 로드되면 Runtime Data Area에 배치되기 전에 바이트코드에 대해 검증 절차를 가지게 되는데, 주요 내용은 다음과 같다.
    ① 코드가 JVM이 명시한 내용과 일치한지 여부
    ② 메모리에 허가되지 않은 접근이 존재하는지 여부
    ③ Stack Over Flow 체크
    ④ Data Types 체크
   ⇒ 데이터코드를 해석하고 검증하는 과정을 가지면서 프로그램의 접근을 제한하고 시스템 외부에 비정상적인 영향을 끼치는 것을 방지 (보안성 증가)

참고자료

(2) 실행 데이터 영역(Runtime Data Area)
      : 자바 프로그램을 실행하기 위해 OS에서 할당받은 메모리 공간. JVM은 이 영역에 자바 프로그램에서 사용하는 데이터들을 적재한다. 실행 데이터 영역은 크게 5가지로 나뉜다

  • 메소드 영역(Method Area)
    • 클래스 영역(Class Area), 스태틱 영역(Static Area)이라고도 부른다.
    • 코드에서 사용되는 클래스, 메소드 정보와 클래스 변수 정보를 저장
    • 상수 풀(Constant Pool)이 존재
    • 프로그램 시작부터 종료될 때까지 메모리에 적재
    • 모든 스레드가 공유함

      상수 풀(Constant Pool)이란?
         : 상수 자료형을 저장하고, 동일한 값의 중복을 막아 메모리 낭비를 방지하는 역할. 이미 있는 값이 들어오면 새로 만들지 않고 먼저 들어있던 같은 값의 주소를 같이 참조하게 한다.

  • 힙 영역(Heap Area)
    • 런타임 시 동적으로 메모리 할당
    • 참조 자료형과 new 연산자를 통해 생성된 객체(인스턴스)가 저장
    • 가비지 컬렉터가 관리하는 메모리 영역
    • 모든 스레드가 공유함
  • 스택 영역(Stack Area)
    • 컴파일 시 결정되는 임시 데이터(기본 자료형과 참수변수)가 저장
    • 메서드가 호출될 때마다 각각의 스택 프레임이 생성되며, 각 스택 프레임은 하나의 메소드에 대한 정보를 저장
    • 각 스레드 마다 생성 (공유X)
  • PC register
    • JVM이 수행할 명령어의 주소를 저장하는 공간
    • 스레드가 시작될 때마다 생성
    • 각 스레드 마다 생성
  • Native Method Stack
    • 자바 외 언어(C/C++)로 작성된 코드를 수행하기 위한 메모리. 스레드에서 네이티브 방식의 메소드가 실행되면 이곳에 쌓이게 된다.
참고자료

(3) 실행 엔진(Execution Engine)

  • 인터프리터(Interpreter)
    : 바이트코드를 직접 한 줄씩 번역한 다음 바로 실행시키는 방법. 인터프리터를 실행시키면 해당 파일의 첫번째 줄을 읽어 기계어 명령어로 번역한 후 CPU에 바로 돌린다. 오류 발생 시 전체를 컴파일하지 않아도 돼서 디버깅에 편하지만, 컴파일 방식보다 시간 효율성이 떨어진다. (자바가 비교적 느리다고 하는 이유)

  • JIT 컴파일러(JIT Compiler)
    : 인터프리터를 보완하기 위해 만들어진, 인터프리터와 컴파일러를 혼합한 방식. 실행 시점에서 인터프리트 방식으로 기계어 코드를 생성하면서 그 코드를 캐싱하여 다음에 같은 코드가 있으면 번역하지 않고 캐싱해둔 값을 사용한다.
    ⇒ 매번 기계어 코드가 생성되는 것을 방지하여 인터프리터의 느린 실행 성능을 개선함

  • 가비지 컬렉터(Garbage Collector)
    : 메모리 관리 기법 중의 하나로, 프로그램이 동적으로 할당했던 메모리 영역(=힙영역) 중 필요없게 된 영역을 해제하는 기능이다. 자바의 메모리 누수 현상(Memory Leak)을 방지한다.
    가비지 컬렉션 기능 및 동작 문서 바로가기

참고자료

(4) JNI (Native Method Interface) / Native Method Library
   : 자바 외 언어(C, C++)로 작성된 코드를 자바에서 실행할 수 있도록 해주는 기능. Native Method Library를 이용해 C, C++의 함수를 호출하여 동작한다.


3. JDK, JRE, JVM 관계

이미지출처

(1) JDK(Java Development Kit) : 자바 개발 도구
   : 자바 기반 프로그램을 개발하기 위한 도구들로 이뤄진 패키지(컴파일러 + 디버거 + JRE 등 포함)

(2) JRE(Java Runtime Environment) : 자바 실행 환경
   : 자바 프로그램을 실행하기 위한 도구들로 구성된 패키지(JVM + Class Library 등 포함)


4. 자바 프로그램 실행 과정

(1) 자바 컴파일러(javac)가 자바 소스코드(.java)를 읽어들여 자바 바이트코드(.class)로 변환

(2) Class Loader를 통해 class 파일들을 JVM에 로딩

❗ 헷갈리는 개념 짚고 넘어가기

그림 참고 자료

JVM은 자바 프로그램을 실행하기 위한 '프로그램'이기 때문에 JVM 실행 시 메모리(RAM)에 적재된다. 또한, class 파일을 JVM에 로딩하기 위해서는 보조기억장치(하드디스크)에 저장되어 있던 class 파일을 메모리(RAM)에 불러와야 한다.
⇒ 즉, Class Loader 실행을 위해선 (1) JVM을 실행, (2) class 파일을 RAM에 적재, 이 두 가지가 수행되어야 한다.

(3) 로딩된 class 파일들은 실행엔진(Execution engine)을 통해 기계어로 해석

(4) 해석된 코드는 실행 데이터 영역(Runtime Data Area)에 배치되어 실질적인 수행이 이루어짐



참고영상
추가자료

profile
오지는 갓생 살기

0개의 댓글