Middleware/Tuning

Java JVM 구조

Cloud Applicaiton Architect 2021. 7. 26. 13:39
반응형

JVM 이란

Java virtual machine (JVM) is a virtual machine that enables a computer to run Java programs as well as programs written in other languages that are also compiled to Java bytecode. The JVM is detailed by a specification that formally describes what is required in a JVM implementation. Having a specification ensures interoperability of Java programs across different implementations so that program authors using the Java Development Kit (JDK) need not worry about idiosyncrasies of the underlying hardware platform. (Wikipidia)

JVM(Java Virtual Machine)은 컴퓨터에서 Java 프로그램과 Java 바이트코드로 컴파일된 다른 언어로 작성된 프로그램을 실행할 수 있도록 하는 가상 머신입니다. JVM은 JVM 구현에 필요한 사항을 공식적으로 자세히 설명하고 있습니다. 사양을 잘 준수하고 있다면 다양한 환경에서 구현된 Java 프로그램의 상호 운용성이 보장되므로 JDK(Java Development Kit)를 사용하는 프로그램 작성자는 기본 하드웨어 플랫폼의 특성에 대해 걱정할 필요가 없습니다.

이를 좀 더 간략히 표현하면, 

  • Java Virtual Machine, 즉 JVM은 Java bytecode를 해석하고 실행하는 주체로 JRE에서 가장 중요한 요소 중 하나임
  • "Write Once, Run Anywhere" 의 구현체
    • 다양한 하드웨어, OS 위에서 동작할 수 있도록 구현됨
  • 자바 어플리케이션을 Class Loader를 통해 읽어 들여 자바 API와 함께 실행

으로 표현 할 수 있음

JVM의 구조

 

 

Java의 컴파일러가 자바의 소스코드(.java 파일)를 빌드하면 바이트코드 파일(.class 파일)이 생성된다. 각 운영체제의 JVM의 Class Loader가 이 바이트코드 파일을 Runtime Data Areas에 로딩하여 프로그램을 구동한다.

Class Loader

Class Loader의 로딩은 런타임에 일어나는데, 클래스에 처음 접근될 때 일어난다. 이를 이용해 Lazy Loading Singleton 같은 것들을 구현하기도 한다. 참고로 Class Loading 시간엔 thread-safe하다.

 

Class Loader 구조

 

Java의 동적 클래스 로딩 기능은 ClassLoader 하위 시스템에 의해 처리한다. 컴파일 시간이 아니라 런타임에 처음으로 클래스를 참조할 때 클래스 파일을 Loading, Linking 및 Initialization한다.

  1. Loading
    클래스를 읽어 들이는 실질적인 주체. BootStrap ClassLoader, Extension ClassLoader 및 Application ClassLoader라는 세 가지 ClassLoader가 존재한다.
    • BootStrap ClassLoader – 부트스트랩 클래스 경로에서 클래스를 로드하는 일을 담당하며 rt.jar를 읽는다. 이 로더에 가장 높은 우선 순위가 부여된다.
    • Extension ClassLoader – ext 폴더(jre\lib) 내부에 있는 클래스 로드를 담당한다.
    • Application ClassLoader – Application Level Classpath, 언급된 환경 변수 등의 로드를 담당한다.
  2. Linking
    • Verify– 바이트 코드를 검증하는 역할로 생성된 바이트 코드가 올바른지 여부를 확인한다. 확인에 실패하면 확인 오류가 발생한다.
    • Prepare- 모든 정적 변수에 대해 메모리가 할당되고 기본값이 할당된다.
    • Resolve- 모든 Symbolic memory references는 'Method Area'의 'Original references'들로 대체된다. 
  3. Initialization
    Initialization 단계는 ClassLoading의 마지막 단계로써, 이 단계에서 모든 static variable의 값이 original 값으로 할당되고, static block도 실행된다.

 

Runtime Data Areas

OS로부터 할당받은 JVM의 메모리 영역이다. 자바 애플리케이션을 실행하는데 필요한 데이터를 담는다. Runtime Data Areas는 Method Area, Heap Area, Stack Area, PC Registers, Native Method Stack이라는 5개의 주요 영역으로 나뉘어 있다.

Runtime Data Area의 구조

Method Area

  • Class Loader가 적재한 클래스(또는 인터페이스)에 대한 메타데이터 정보(각각의 클래스, 인터페이스에 대한 런타임 상수 풀, 필드, 메소드 정보, static 변수, 메소드의 바이트코드 등)가 저장됨
  • Non-Heap 영역으로 Permanent 영역에 저장됨
  • JVM 옵션 중 PermSize(Permanent Generation의 크기)를 지정할때 고려해야 할 요소
  • Method Area는 아래의 정보들을 저장한다.
    • Type Information
      - Interface 여부
      - 
      패키지 명을 포함한 Type 이름
      - Type
      의 접근 제어자
      - 
      연관된 Interface 리스트
    • Runtime Constant Pool
      - Type, Field, Method로의 모든 레퍼런스를 저장
      - JVM
       Runtime Constant Pool을 통해 실제 메모리 상 주소를 찾아 참조한다.

    • Field Information
      - Field의 타입
      - Field
      의 접근 제어자
    • Method Information
      - Constructor를 포함한 모든 Method의 메타데이터를 저장
      - Method
      의 이름, 파라미터 수와 타입, 리턴 타입, 접근 제어자, 바이트 코드, 지역 변수 section의 크기 등을 저장

    • Class Variable
      - static 키워드로 선언된 변수를 저장
      - 
      기본형이 아닌 static 변수의 실제 인스턴스는 Heap 메모리에 저장

Heap Area

 new 연산자로 생성된 객체를 저장하는 공간이다.
• 참조하는 변수나 필드가 존재하지 않으면 GC의 대상이 된다.
• 모든 개체와 해당 인스턴스 변수 및 배열이 여기에 저장됩니다.

JVM Heap 구조

단, JDK7까지는 permanent영역이 heap에 존재했었으나 JDK8부터는 permanent 영역은 사라지고 일부가 "meta space 영역"으로 변경되었다.(위의 그림 JDK7 기준.) meta space 영역은 Native stack 영역에 포함되었습니다.

(survivor영역의 숫자는 의미없고 두 개로 나뉜다는 것이 중요하다)

힙 영역을 굳이 5개로 나눈 이유는 효율적으로 GC가 일어나게 하기 위함이다. 자세한 것은 GC가 일어나는 프로세스를 보면서 설명한다.

JVM 7 vs JVM 8 아키텍처 비교

 

Stack Area

  • JVM 내에서 메소드가 수행 될 때마다 메소드 호출에 대한 정보를 저장하기 위해 생성되는 Stack Frame 이라는 구조체를 저장하는 스택• 지역 변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값등이 생성되는 영역이다.
  • int a = 10; 이라는 소스를 작성했다면 정수값이 할당될 수 있는 메모리공간을 a라고 잡아두고 그 메모리 영역에 값이 10이 들어간다.
  • 즉, 스택에 메모리에 이름이 a라고 붙여주고 값이 10인 메모리 공간을 만든다.
  • 클래스 Person p = new Person(); 이라는 소스를 작성했다면 Person p는 스택 영역에 생성되고 new로 생성된 Person 클래스의 인스턴스는 힙 영역에 생성된다.
  • 예외 발생 시 printStackTrace() 등의 메소드로 보여주는 StackTrace의 각 라인은 하나의 stack frame을 표현함
  • Thread마다 별개의 Frame으로 저장하며, 아래의 정보들을 저장한다.
    • Local Variable Area
      - 지역변수, 매개변수, 메소드를 호출한 주소 등 Method 수행 중 발생하는 임시데이터를 저장한다.
      - 4
      바이트 단위로 저장되며, int, float  4바이트 기본형은 1개의 셀, double  8바이트의 기본형은 2개의 셀을 차지한다. bool은 보통 1개의 셀을 차지한다.
    • Operand Stack
      - Method workspace이다.
      - 
      어떤 명령을 어떤 피연산자로 수행할 지 나타낸다.
    • Frame Data
      - Constant Pool Resolution, Method Return, Exception Dispatch 등을 포함한다. 또한 참조된 Exception의 테이블도 가지고 있다.
      - Exception
      이 발생하면 JVM은 이 테이블을 참고하여 어떻게 Exception을 처리할 지 정한다.

 

PC Registers

  • Thread가 현재 실행하고 있는 부분의 주소를 저장한다.
  • OS는 PC(Program Counter) Register를 참고하여 CPU 스케줄링 시 해당 Thread가 다음에 어떤 명령어를 수행해야 하는지 알 수 있다.

 

Native Method stacks

  •  Java 이외의 언어로 작성된,  JNI(Java Native Interface)를 통해 호출하는 C/C++ 등의 코드를 수행하기 위한 스택

 

Execution Engine

Runtime Data Area에 할당된 바이트코드는 Execution Engine에 의해 실행된다. Execution Engine은 바이트코드를 읽고 조각(piece)별로 실행한다.

Execution Engine

Interpreter

Interpreter는 바이트 코드를 빠르게 해석해 천천히 실행한다. 인터프리터의 단점은 하나의 메소드가 여러 번 호출될 때마다 새로운 해석이 필요하다는 것이다.

JIT Compiler

JIT Compiler는 Interpreter의 단점을 보완한다. Execution Engine은 바이트 코드를 변환할 때 인터프리터의 도움을 사용하지만 반복되는 코드를 찾으면 전체 바이트 코드를 컴파일하고 네이티브 코드로 변경하는 JIT Compiler를 사용한다. 이 기본 코드는 반복되는 메서드 호출에 직접 사용되어 시스템 성능을 향상시킵니다.

Garbage Collector

  • JVM에서 더이상 참조되지 않은 개체를 수집하고 제거한다.
  • 가비지 컬렉션은 System.gc()를 호출하여 인의적으로 실행할 수 있지만 실행이 보장되지는 않는다.
  • JVM의 가비지 컬렉션은 생성된 개체를 수집한다.

 

Java Native Interface(JNI)

JNI는 Native Method Library와 상호 작용하고 실행 엔진에 필요한 Native Library를 제공한다.

차례로 Execution Engine , Java Native Method Interface 그리고 Java Method Library

 

Native Method Libraries

Execution Engine에 필요한 Native Libraries 모음

 

Reminder!

 

반응형

'Middleware > Tuning' 카테고리의 다른 글

JVM 옵션을 통한 성능 튜닝 이해  (0) 2021.08.13
Java GC 알고리즘 및 주요 옵션  (0) 2021.07.28
Java Heap 메모리 옵션  (2) 2021.07.26