ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java-4] JVM의 구조
    Java 2020. 11. 11. 12:30

    전 글에서는 JVM에 대해서 간단하게 알아 보았다. 이제 JVM 구조에 대해서 알아보고 JRE와 JDK 에 대해서 알아보도록 하자. 

     

    1. JVM 구조 

    JVM 의 구성요소는 크게 3가지로 구성 되어있다.

    1. 클래스 로더 시스템 (Class Loader)

    2. 메모리 (Jvm Memory)

    3. 실행 엔진 (Execution Engine)

     

    전체적인 그림이다. 

    JVM의 전체적인 구조 이다. 출처 : https://www.elfanmauludi.id/2019/03/fungsi-java-virtual-machine-atau-jvm.html 

    1-1. 클래스 로더 시스템 

     

    이렇게 3가지의 구조로 되어있습니다. 클래스 로더 시스템은 말 그대로, 클래스를 읽어오는 시스템 구조인데, 로딩 -> 링크 -> 초기화 순으로 진행이 됩니다. 

     

    클래스 로더의 구조

    그림으로 표현하면 다음과 같은데, 자세하게 다루지는 않고, 각자 무슨 역할을 하는지 확인해보자, 

     

    로딩 시점에는 클래스가 있는지 없는지 확인하게 되는데 만약에 없을 경우, 이 시점에서 “Class Not Found Exception”이 발생 하게 된다.

     

    String클래스는 있지만, StudyHalle의 클래스는 없으므로 ,

     

    이런식으로 에러가 발생되게 된다. 클래스가 있다면, 그 파일을 읽고 JVM 구조의 클래스로더의 다음 단계인 메모리의 메서드 스택 영역에 저장된다. 



    1-2. 메모리

    JVM 스펙에 정의된 메모리 구조

    (1)힙

    힙은 인스턴스화 된 모든 클래스 인스턴스와 배열을 저장, 객체를 저장하게 되는데, 모든 JVM 스레드에 공유 되는 공유 자원 이다. 힙에 저장된 할당된 메모리 회수 권한은 무조건 가비지 컬렉터(Garbage Collector)에 의해서만 회수가 가능하다. 

     

    (2)메소드

    메서드 영역에서는 런타임 상수풀, 필드와 메소드 데이터 내용, 즉 클래스 수준의 정보를 저장하게 된다. 

    그림에서는 힙과 메서드 영역을 분리하였지만, jvm 스펙에서는 메소드 영역이 논리적으로 힙의 일부여서 가비지 컬렉션에 대상이 된다고 하지만, 강제적으로 메소드의 영역의 위치에 대해서 논하지 않는다고 한다. 즉, JVM 을 회사를 만드는 회사마다, 저 그림은 상이할 수 있다는 얘기다. 

     

    (3)PC 레지스터

    PC레지스터는 현재 실행중인 메서드가 네이티브가 아니면, 현재 실행중인 JVM 명령어 위치에 저장되고, 네이티브이면 Pc 레지스터에 저장되는 값은 정의되지 않는다.
    CPU의 Register와는 다르게,  연산을 위해 필요한 피연산자를 임시로 저장하기 위한 용도로 사용한다.

     

    (4)스택 (JVM Stack이라고도 불린다.)

    LIFO동작으로 동작하는 자료구조 로써, 쓰레드 마다 런타임 스택을 만들고, JVM 스택에는 프레임에 저장된다. 메서드 하나가 호출될 때마다 새 프레임이 생성되어 스택에 쌓이고, 메서드 호출이 정상 완료되거나 예외가 던져지면 프레임은 스택에서 빠지면서 소멸된다. 또한 쓰레드가 종료되면 스택도 제거된다. 

     

    (5)네이티브 메소드 스택(Native Method stack)

    네이티브 메서드 스택은 JVM의 스택이 아니라 C 스택을 가르킨다. 자바가 아닌 다른 언어로 작성된 네이티브 메서드를 지원하기 위해 사용되는 스택이다. 네이티브 메소드 스택은 JVM 스택과 마찬가지로 스레드 단위의 자료구조 이다. 

     

    진짜 너무너무 간단하게만 설명한 내용이다. 더 자세한 동작을 알고싶다면 이 블로그를 참고하면 너무 좋다. 

     

    1-3. 실행 엔진(Execution Engine)

     

    실행에서 저번에 이전글에서 작성했던 JIT에 대한 글을 보면 좀 더 재밌을 것이다. 실행엔진은 말 그대로 클래스 로딩 과정을 통해 런타임 데이터 영역에 배치된 바이트 코드를 명령어 단위로 읽어서 실행하게 됩니다. 

    이제 이 과정을 수행하고 기계가 읽을수 있는 코드로 변경을 해주는데, 이때 사용되는게 인터프리터와 JIT컴파일러 이다. 

     

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

    JVM에서는 C , C++, 어셈블리어로 구축한 네이티브 한 함수를 네이티브 메서드라고 한다. JNI란 네이티브 메소드를 호출 할 수 있는 방법을 제공을 한다. 

     

    그럼 네이티브 메소드를 왜 사용하는 걸까? 몇가지 적어보도록 하자

    1. 이미 다른 언어로 상당히 크고 중요한 코드를 작성했고, 자바로 동일한 코드를 재작성하기를 원치않을 때

    2. 자바가 시스템 디바이스에 접근 하거나, 플랫폼 특정적인 작업을 할 때 사용하도록 한다.

    3. 자바로 구현하기엔 어플리케이션이 너무 느릴 수 있어서, C 언어를 사용해서 성능향상을 위해서 작성하기도 한다. 

    예를들어 Thread 클래스의 몇가지 메소드는 native로 작성되어있는데 확인하는 방법이

     

    다음과 같이 native 라고 적혀 있다. 

     

    이런 네이티브한 메소드를 저장한게 네이티브 메소드 라이브러리 이다. 


    JNI에 대해서 찾아보다가 Effective Java 에서 native method의 사용은 신중해야 한다는 글이 있어, 흥미로워서 참고한다.

     

    다음은 JDK 와 JRE에 대해서 알아보도록 하자 

    > [Java-5] JDK& JRE, 자바 실행

     

    'Java' 카테고리의 다른 글

    [Java-6] Java 기본 타입 (primitive)  (0) 2020.11.16
    [Java-5] JDK& JRE, 자바 실행  (2) 2020.11.11
    [Java-3] JVM과 JIT 컴파일러란?  (2) 2020.11.10
    [Java-2] 바이트 코드란  (1) 2020.11.09
    [Java-1] 컴파일 방법 & 과정  (13) 2020.11.09

    댓글

Designed by Tistory.