Chat 상우

[java] JVM(Java Virtual Machine) 메모리 구조와 실행 원리 본문

카테고리 없음

[java] JVM(Java Virtual Machine) 메모리 구조와 실행 원리

chat-rilla 2023. 10. 27. 17:09

IT 강사 chat 상우입니다.

오류가 있거나 수정되어야 할 부분은 댓글 남겨주시면 감사하겠습니다.

 

JVM 구조와 작동 원리

JVM은 java의 프로그램을 실행하기 위한 핵심 컴포넌트 중 하나로, java 코드를 기계어 코드로 변환하고 실행하는 역할을 하는 가상 머신으로 간략하게 컴파일 과정을 통해 java 코드를 class 파일로 변역하여 jvm이 인식을 할 수 있도록 변환한뒤 클래스 파일을 읽어온뒤 여러 과정을 거친 다음 바이트 코드로 변환하고 OS에 명령을 전달하는 역할을 담당하게 된다.

 

JVM 실행 구조

  1. Class Loader SubSystem :
    java 클래스 파일을 로드하고 클래스들을 jvm 내에 로드하는 역할을 수행하며 프로그램 클래스 로딩 및 동적 클래스 로딩을 처리하는 역할을 갖는다.
  2. Methode Area : 
    jvm 메모리 구조의 중요한 부분 중 하나로, 클래스 정보와 메서드 코드, 정적 변수 및 상수 풀 등을 저장하는 영역이다.
    • 클래스 정보 저장 : 로드된 클래스의 정보를 저장한다.
    • 정적 변수 저장(static) : 클래스의 정적 변수로 Method Area에 저장된다. 정적 변수의 경우 클래스 레벨에서 공유가 되며, 클래스 로드 시 초기화되어 모든 인스턴스에서 공유하게 된다.
    • 상수 풀(Constant Pool)  : 상수 풀은 클래스의 상수 및 리터럴 값들을 저장하는 테이블이다.
      클래스 파일 내에서 참조된 상수들이 여기에 저장된다.
    • 메서드 코드 저장 : 클래스의 메소드에 대한 바이트 코드가 Method Area에 저장되어 바이트 코드는 클래스 로드시 파싱되어 실행된다.
    • 런타임 상수 풀(Runtime Constant Pool) : 런타임 상수 풀은 클래스 파일의 상수 풀에 저장된 상수들을 런타임 중에 참조하기 위한 테이블로 상수들은 실제 런타임 값으로 매핑하는 역할을 한다.
  3. Heap :
    java 프로그램에서 동적으로 할당되는 객체와 데이터를 저장하는 메모리 영역으로 heap은 프로그램 실행 중에 동적으로 생성되는 객체를 저장하고 관리하는 공간으로, 다른 메모리 영역과 대비된다.
    1. 동적 메모리 할당 : heap은 java 프로그램에서 객체와 배열을 동적으로 할당하는데 사용되며 프로그램에서 new 키워드를 사용하여 객체를 생성할 때 해당 객체는 heap 영역에 할당을 하게 되는 것이다.
      객체의 크기와 생존 기간은 동적으로 관리가 된다.
    2. 가비지 컬렉션 : heap에 저장된 객체 중에서 사용되지 않는 객체(가비지)는 가비지 컬렉션에 의해 주기적으로 정리가 되어 메노리 누수를 방지하고 프로그램의 성능을 유지하는데 도움을 준다.
    3. 메모리 분할 : heap은 논리적으로 세그먼트를 나누어질 수 있으며, 일반적으로 두 가지 주요 영역으로 구분된다. 
      Young Generation과 Old Generation으로 구분하여 young의 영역에는 새로 생성된 객체를 저장하고 old에는 생존한 객체를 저장한다.
    4. 성능 최적화 : heap의 크기 및 구성은 jvm의 성능에 영향을 주게될 수 있는데 heap의 크기를 조절하여 GC 알고리즘 및 힙 분할 방법을 설정하여 프로그램의 성능을 최적화할 수 있다.
    5. 스레드 간 공유 : heap은 jvm내의 모든 스레드 간에 공유되며 다수의 스레드가 동시에 heap에 엑세스하고 객체를 생성하거나 참고할 수 있게 된다.
      JVM Heap 메모리 공간
      Heap 메모리 구조
  4. Java Stacks
    1. 호출 스택(call Stack) : 메소드를 호출할 때 메소드 호출 정보를 저장하는데 사용되는 자료구조 이며 이 스택은 호출된 메소드의 호출 프레임을 저장하여 각 호출 프레임은 해당 메소드의 지역 변수, 매개 변수, 반환 주소 등을 포함한다.
      호출스택은 메소드의 호출과 반환을 추적하여 프로그램의 실행 흐름을 관리하게 되는데 스택에 쌓인 가장 위의 호출 프레임이 현재 실행 중인 메소드를 나타내며 호출이 완료되면 해당 프레임 스택에서 제거되게된다.
    2. 데이터 스택(data stack) : 데이터 스택은 jvm이 연산을 수행할 때 중간 결과 및 연산자를 저장하는데 사용되는 자료구조이며 이 스택은 산술 연산, 비트 연산, 논리 연산 등을 수행할 때 중간 결과를 보관하며, 연산의 결과를 다른 연산에 사요요하거나 반환할 때 사용하게 된다.
    3. 데이터 스택은 jvm 명령어 실행중 데이터를 보관하는데 필요하며 jvm 스택 프레임 내의 로컬 변수 스롯과 연관되어 데이터를 처리하게 된다.
  5. Pc Registers : 프로그램 실행 중에 현재 실행 중인 명령어의 주소를 추적하는데 사용되는 것이다.
    1. 명령어 주소 추적 : pc 레지스터는 현재 실행 중인 명령어의 주소를 가리킨다.. 
    2. 명령어 실행 : pc 레지스터가 가리키는 명령어가 실행되고 jvm은 프로그램 카운터를 증가시켜 다음 명령어로 이동하여 명령을 실행하는 방식으로 실행 순서를 유지한다.
    3. 분기 및 제어 프름 : pc 레지스터는 분기 명령어(반복무느 조건문)과 같은 제어 흐름 명령을 처리할 때 중요한 역할을 하게 되며 프로그램 카운터를 변경하여 분기되어야 할 새로운 명령의 주소로 이동하여 프로그램의 흐름을 제어한다.
    4. 예외 처리 : jvm은 예외 처리를 할 때 pc 레지스터를 이용하여 예외 핸들러의 위치로 이동하고 이를 통해 예외가 발생한 후 적절한 처리를 가능하게 만든다.
    5. 메서드  호출 및 반환 : 메서드 호출과 반환 시에 pc 레지스터는 호출된 메서드의 반환 주소를 저장하고, 반환 시 해당 주소로 이동하여 호출 스택을 관리하게 된다.
  6. Native Method Stacks 
    Java Virtual Machine(Jvm) 내에서 네이티브 메서드, 즉 java의 바이트 코드가 아닌 네이티브 언어 (C, c++)로 작성된 메서드의 실행을 관리하게되는 메모리 영역이다. 
  7. Execution Engine
    실행 엔진이라고 불리우는  java의 바이트 코드를 실행하는 핵심 구성 요소로, java 프로그램의 동작을 제어하고 명령어를 해석하거나 컴파일하여 기계 코드로 실행하게 된다.
    1. Just-In-Time(jit) 컴파일 : 자바의 바이트 코드를 기계어로 변환하는 것으로 과거에는 바이트 코드를 순수하게 인터프리트 하여 매우 느린 성능을 보였으나 현재는 JIT 컴파일러를 도입과 하드웨어의 발전으로 성능이 매우 우수하게 향상되어 있는 상태이다.

 

 

 

JVM 메모리 구조
JVM 메모리 구조 - 출처 : 나무위키