티스토리 뷰

JVM( Java Virtual Machine )


 

 

한 문장으로 설명하는 JVM
OS에 종속적이지 않은 바이트 코드를 각 OS에 맞게 컴파일하고 실행하는 가상 머신 

 

JVM은 클래스 파일(바이트 코드)을 메모리에 적재하고 실행(네이티브 코드로 컴파일)한다. 자바 언어에는 의존하지 않고 바이트 코드에 의존하는데 그렇기 때문에 바이트 코드로 컴파일될 수 있는 모든 언어(코틀린, 스칼라..)는 JVM위에서 실행될 수 있다. 

자바 언어가 OS에 독립적일 수 있는 이유도 이 플랫폼에 종속적인 JVM이 중간단계로 있어 Java언어를 OS에서 분리하기 때문이다.

 

  • JVM은 Java언어에 대해 알고 있지 않고, 바이트코드인 class 만 알고 있다.
  • 바이트코드로 변환될 수 있는 모든 언어는 JVM위에서 실행 가능하다.
  • java언어는 플랫폼에 독립적이지만, JVM은 플랫폼(OS)에 종속적이다.

 

바이너리와 바이트코드


 

바이너리 코드(Binary Code)

  • 바이너리 코드는 대개 컴퓨터가 이해할 수 있는 이진 코드(0과 1로 구성된)를 얘기하는데, 모든 바이너리 코드가 이진 코드인 것은 아니다.

바이트코드(Byte Code)

  • 바이트코드는 JVM이 이해할 수 있는 바이너리 코드로 가상 머신을 위한 기계어다.
  • 바이트코드는 1byte 크기의 opcode(operation code : 명령 코드)로 현재 약 200여 개의 명령어로 구성되어 있다 (256개 가능)
  • 인터프리터 혹은 JIT 컴파일러에 의해 네이티브 코드로 변환되어 실행한다.

 

 

 

JVM의 구성요소


 

 

 

클래스 로더 시스템


클래스파일을 JVM 메모리에 적재하는 작업을 한다.  로딩 -> 링크 -> 초기화 순으로 진행된다.

 

1. 로딩 (loading)

  1. 클래스 로더를 통해. class 파일을 읽고 바이너리 데이터를 만들어 메서드 영역에 저장한다.
  2. 메서드 영역에 저장하는 데이터
    1. FQCN(Fully Qualified Class Name)
    2. Class, Interface, Enum
    3. Modifier(제어자), 변수, 메서드
  3. 로딩 이후 Class Type 객체를 생성하여 힙 영역에 저장한다
Modifier (제어자) 종류
접근 제어자 : public protected default private
기타 : static final abstract native transient synchronized vloatile strictfp

 

 2. 링크 (linking)

  1. Verify → Preparation → Resolve
    1. Verify :. class 파일 형식이 유효한지 체크한고 실패 시 VerifyError 발생
    2. Preparation : 클래스 변수(static 변수)에 메모리를 할당 후, 메모리를 기본값으로 초기화
    3. Resolve : 심볼릭 메모리 레퍼런스를 메서드 영역에 있는 실제 레퍼런스로 교체 (Optinal)

 

3. 초기화(initialization)

  1. 모든 static 변수에 값을 할당한다.

 

빌트 인 클래스 로더

  • 부트스트랩 클래스 로더(Bootstrap class loader)
    • JAVA_HOME/lib" 디렉터리에 있는 핵심 자바 API 클래스를 로드, C, C++ 같은 네이티브 언어로 구현.
  • 확장 클래스 로더 (Extension class loader)
    • "JAVA_HOME/lib/ext" 또는 java.ext.dirs 시스템 속성으로 지정된 디렉터리에 있는 클래스를 로드.
  • 애플리케이션 클래스 로더(System/Application class loader)
    • 애플리케이션 클래스 경로에 있는 클래스를 읽는다. 보통 -classpath 옵션이나 환경변수로 설정한 위치에 클래스를 읽어온다.

 

 

메모리


Per-Thread

  • 스택 (stack)
    • 모든 스레드에 대해 JVM은 스택 영역에 런타임 스택을 생성하고, 메서드 호출 시 스택 프라임을 쌓는다.
  • PC(Program Counter) Register
    • 모든 스레드의 현재 실행할 스택 프라임 위치를 가리키는 포인터 생성된다.
  • 네이티브 메소드 스택
    • 모든 스레드에 네이티브 메서드 호출 스택을 저장할 네이티브 메소드 스택을 생성한다.
    • 네이티브 메소드 : 네이티브 언어(C, C++)로 작성된 메소드

Common-Area

  • 메소드 영역 (Method Area)
    • Static 변수를 포함한, 클래스 이름, 부모 클래스 이름, 메서드, 변수 정보가 저장된다.
  • 힙 영역 (Hip Area)
    • 모든 클래스와 배열의 객체가 저장된다.
    • 클래스 로더 시스템의 로딩 단계 이후 클래스 타입 인스턴스가 이곳에 저장된다.

 

실행 엔진( Execution Engine )


 

 

1. 인터프리터(Interpreter)

  • 바이트 코드를 한 줄씩 읽어가며 OS가 이해할 수 있는 네이티브 코드로 해석하여 실행합니다.

2. JIT 컴파일러

  • 실행 엔진은 기본적으로 인터프리터로 변환하다가 특정 조건에 맞는 HotSpot에 경우 메서드의 바이트코드를 컴파일하여 네이티브 코드로 변경하는 JIT 컴파일러를 사용하여 JVM내부에 캐싱해두다가 중복된 코드가 발생하면 바로 사용하는 것으로 최대 효율의 성능을 낸다

3. 네이티브 메서드 인터페이스( JNI : Java Native Method Interface )

  • Java코드가 네이티브 코드로 작성된 애플리케이션이나 라이브러리를 호출하거나 반대로 호출될 때 중계자 역할을 하는 프레임워크.

4. 네이티브 메서드 라이브러리( Native Method Liabrary )

댓글