[Java] JVM Structure

홍정완·2022년 7월 27일
0

Java

목록 보기
17/25
post-thumbnail

JVM Structure


자바 개발자라면 한정된 메모리를 효율적으로 사용하고 최적의 퍼포먼스를 내기 위해 JVM(Java Virtual Machine)을 잘 알아둬야 한다. 프로그램의 성능은 알고리즘 외에도 메모리 관리와 매우 밀접하게 연결되어 있다.


JVM은 자바 프로그램의 생명 주기 전체를 관장하며 리소스를 할당하고 메모리를 관리한다.


  • 시스템 가상머신의 의미보다는 프로세스 가상머신의 뜻으로 사용

  • 자바 바이트 코드를 OS에 특화된 코드로 변환하고 실행하는 주체 혹은 사양(Spec)




Class Loader System



Class Loader는 자바 바이트 코드를 읽어서 JVM의 Execution Engine이 사용할 수 있도록 Runtime Data Area에 적재하는 역할을 한다.

즉, 자바 클래스들은 한 번에 메모리에 올라오는 것이 아니라, 런타임 시 필요할 때 동적으로 클래스를 로딩하게 된다.



로딩


  • BootStrap Class Loader, 최상위 부모

    • 다른 클래스 로더와 달리 자바가 아니라 네이티브 코드로 구현

  • Extension Class Loader

    • 기본 자바 API를 제외한 확장 클래스들 로드

    • 다양한 보안 확장 기능 등 로드


  • Application Class Loader

    • Application Classpath에서 클래스를 읽고 로드



  • 각 Class Loader는 클래스를 읽다가 로드 요청을 받으면, 캐시 👉 부모 👉자식 순으로 클래스 로딩

    • 불가한 경우 클래스를 읽은 해당 로더가 클래스를 로드



링크


  • Verify

    • .class 파일이 유효한지 유효성 검사 수행

      • 클래스 로드의 전 과정 중, 가장 까다로운 검사 수행 과정, 가장 복잡하고 시간이 많이 걸린다.

  • Preparation

    • 클래스가 필요로 하는 메모리를 할당하고, 클래스에서 정의된 필드, 메서드, 인터페이스들을 나타내는 데이터 구조 준비

  • Resolve

    • 심볼릭 메모리 레퍼런스를 메서드 영역에 있는 실제 레퍼런스로 교체



초기화


  • 클래스 변수들(static)을 적절한 값으로 초기화



메모리(Runtime Data Area)



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


  • 쓰레드마다 개별적 할당

    • PC register
    • Stack
    • Native Method Stack

  • 모든 쓰레드 공유

    • Heap
    • Runtime Constant Pool



PC register

  • PC(Program Counter) 레지스터는 각 스레드마다 하나씩 존재하며 스레드가 시작될 때 생성
  • 현재 스레드가 수행 중인 코드의 주소를 갖는다.

Stack

  • 각 스레드마다 하나씩 존재하며 스레드가 시작될 때 생성
  • 스택 프레임(Stack Frame)이라는 구조체만 저장 가능하며, push, pop으로 동작

Native Method Stack

  • 자바 외에 언어로 작성된 네이티브 코드를 위한 스택

Method Area

  • class 영역이라고도 불리며, 모든 스레드가 공유하는 영역
  • JVM이 시작될 때 생성되고, JVM이 읽어들인 정적으로 판단할 수 있는 데이터의 대부분을 보관

Runtime Constant Pool

  • 각 클래스와 인터페이스의 상수뿐만 아니라, 메서드와 필드에 대한 모든 레퍼런스까지 담고 있는 테이블
  • JVM은 Runtime Constant Pool을 통해 해당 메서드나 필드의 실제 메모리상 주소를 찾아서 참조

Heap

  • 동적으로 인스턴스가 저장되는 공간으로 가비지 컬렉션의 대상
  • 모든 쓰레드가 접근 가능하며, 성능 이슈에도 많은 지분 차지



Execution Engine


Interpreter

  • Class Loader를 통해 JVM 내 Runtime Data Area에 배치된 바이트 코드를 인터프리터가 명령어 단위로 한 줄씩 읽어나가며 실행

JIT 컴파일러

  • 코드를 처음 읽는 시점(동적 시점)에 중복 코드를 찾아 Native Code로 번역

  • 이후 인터프리터가 중복 코드를 만날 때 인터프리팅을 건너뛰고, 캐시에 저장된 Native Code를 사용

    • 느린 속도 보완

GC(Garbage Collection)

  • 더 이상 참조되지 않는 Heap 영역의 인스턴스들을 자동으로 삭제해 주는 역할



JNI(Java Native Interface)

  • 자바 애플리케이션에서 C, C++, 어셈블리로 작성된 함수를 사용할 수 있는 방법 제공
  • Native 키워드를 사용한 메서드 호출

네이티브 메서드 라이브러리

  • C, C++로 작성된 라이브러리

    • ex) Thread.currentThread();
profile
습관이 전부다.

0개의 댓글