8 Jul 2020

java jvm

Java jvm

jvm은 java와 os사이에서 중개자 역할을 하며 java가 os에 구애받지 않고 재사용을 가능하게

해준다. 그리고 메모리관리, GC를 수행한다.

그리고 jvm은 스택기반이다.


자바프로그램 실행과정

  1. 프로그램이 실행되면 JVM은 OS로부터 이 프로그램이 필요로 하는 메모리를 할당 받는다. JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다.
  2. 자바 컴파일러(javac)가 자바 소스코드(.java)를 읽어 자바 바이트코드(.class)로 변환
  3. Class Loader를 통해 class파일들을 JVM으로 로딩한다.
  4. 로딩된 class파일들은 Execution engine을 통해 해석된다.(로딩된 바이트 코드->바이너리 코드로 변경)
  5. 해석된 바이트 코드는 Runtime Data Area에 배치되어 실질적인 수행이 이루어지게 된다. 이러한 실행 과정 속에서 JVM은 필요에 따라 Thread Synchronization과 GC같은 작업을 한다.


jvm 구성

jvm구조

  1. Java Complier: java 소스 파일을 jvm이 해석할 수 있는 Java Byte Code(.class파일)

    로 변경한다. 일반적인 윈도우 프로그램에서는 컴파일이후 어셈블리 파일이 생성된다.

  2. Class Loader: JVM으로 .class파일들을 Load한다. Loading된 클래스들은

    Runtime data area에 배치된다. 일반적인 윈도우 프로그램의 경우 Load는 os가 주도

  3. Execution Engine: Loading된 클래스의 Bytecode를 해석(Interpret)한다. 이 과정에서

    Bytecode가 Binary Code로 변경된다.

  4. Runtime Data Area: JVM이라는 프로그램이 OS로부터 할당 받는 메모리 영역이다.


구성요소 세부설명

클래스 로더(Class Loader)

3가지 역할 담당

  • Loading

  • Linking

  • Inititalzation


1. Loading

클래스 로더는 .class파일을 읽어 바이트 코드를 메소드 영역에 저장한다.

각 .class파일은 JVM에 의해 메소드 영역에 다음의 정보를 저장한다.

  • 로드된 클래스를 비롯한 그의 부모 클래스의 정보

  • class파일이 Class,Interface,Enum과 관련여부

  • 변수나 메소드의 정보등

    .class파일이 로딩된 후에는 JVM은 힙 메모리 영역에 이 파일이 나타내는 클래스 유형의 객체를

    생성한다. 이 클래스 객체를 이용하면 클래스의 이름 및 부모 클래스 이름,메소드,변수 정보를

    보여줄 수 있다.


2. Linking

verification(증명), preparation(준비), resolution 3가지를 수행한다.

  • Verification : .class파일의 정확성을 보장한다. 파일이 적절히 포맷되었는지,유효한 컴파일러에 의해

    생성되었는지 확인, 검증 실패시 런타임 에러

  • Preparation : JVM은 메모리를 기본 값으로 초기화 한 후, 클래스 변수들을 위한 메모리를 할당한다.

  • Resolution : symbolic references 를 direct references 로 바꾸는 프로세스.


3. Inititalzation

모든 정적 변수들이 정의된 값으로 초기화 된다.


클래스로더는 3가지 종류가 있다.

  • Bootstrap class Loader : 모든 JVM구현에는 신뢰된 클래스들을 로딩하기위해 부트스트랩 클래스

    로더가 필요하다. 이 로더는 JAVA_HOME/jre/lib 디렉토리에 존재하는 핵심 java API들을 로드한다.

    또한 Java가 아닌 c,c++같은 네이티브언어를 통해 구현되있다.


  • Extension class loader : 부트스트랩 클래스 로더의 자식이다. JAVA_HOME/jre/lib/ext또는

    java.ext.dirs시스템 속성으로 명시된 다른 특정 디렉토리인 확장 디렉토리 안에 존재하는 클래스들을 로드

    한다. java로 구현되어있다.


  • System/Application class loader : 확장 클래스 로더의 자식이다. application class경로부터

    클래스들을 로드한다. 내부적으로 java.class.path에 매핑된 환경변수를 사용한다. 사용자가 만든 .class

    확장자 파일을 이 로더가 로딩하는 것이다.


classloader


JVM은 클래스들을 로드하기 위해 위임-계층(Delegation-Hierarchy)원리를 따른다.

시스템 클래스 로더는 로드 요청을 확장 클래스로더로 요청하고 확장 클래스로더는 부트 스트랩

클래스 로더에게 위임하게 된다.

부트스트랩 로더에서 클래스를 찾지 못하면, 확장 로더에서 찾고 못찾으면 시스템 로더에서 찾게 된다.

마지막으로 시스템로더에서도 클래스 로드를 실패한다면 ClassNotFoundException런타임 에러를

볼 수 있다.


Execution Engine

실행 엔진은 바이트 코드로 된 .class파일을 실행하며 3가지로 분류할 수 있다.

  • 인터프리터(Interpreter) : 바이트코드를 한줄씩 해석하여 실행한다. 단점은 여러번 하나의 메소드를

    호출할 경우 매번 해석을 요청해야하기 때문에 비효율적이다.


  • Just-In-Time(JIT) : 인터프리터 방식으로 실행하다가 적절한 시점에 바이트코드 전체를 컴파일하여

    네이티브 코드로 변경하고 이후에는 인터프리팅 하지 않고 네이티브 코드로 직접 실행하는 방식이다.

    네이티브 코드는 캐시에 보관하기 때문에 컴파일된 코드는 빠르게 수행하게 된다. JIT컴파일러가

    컴파일하는 과정은 바이트코드를 인터프리팅하는 것보다 더 오래 걸리므로 한번만 실행되는 코드면

    컴파일하는 것보다 인터프리팅 하는 것이 유리하다. 그래서 JIT컴파일러를 사용하는 JVM은 내부적으로

    해당 메서드가 얼마나 자주 수행되는지 체크하고, 일정 정도를 넘을때에만 컴파일을 수행한다.


  • 가비지 콜렉터 : 참조되지 않는 객체를 소멸시킨다.


Runtime Data Area


run_time_area

프로그램을 수행하기 위해 os에서 할당받은 메모리 공간


Tags:
0 comments