8월 14일, TIL(항해 1일차)

코코·2023년 8월 14일
0

TIL(Today I Learned)

목록 보기
3/19
post-thumbnail

JVM이란?

  • JVM이란 Java Virtual Machine 약자로 자바가 실행되는 가상환경을 뜻한다. 아래의 그림 처럼 java 파일을 컴파일하여 class 파일로 컴파일로 만들면 JVM에서 실행된다.

  • JVM에서 프로그램이 실행되는 과정은 아래와 같다.

  • 먼저 자바 소스 파일(.java)은 자바 컴파일러를 통해서 운영체제가 읽을 수 있는 바이트 코드(.class)로 변환된다.

  • 이후 클래스 로더가 이 자바 파일(바이트 코드)를 JVM 위에 올려놓고, 자바 인터프리터에 의해 기계어로 변환되어 실행된다.

클래스로더란?

  • 자바는 동적으로 클래스를 읽어오므로(동적 로드), 프로그램이 실행 중인 런타임(바이트 코드를 실행할 때)에서야 모든 코드가 자바 가상 머신과 연결된다. 이 동적 로드를 담당하는 부분이 JVM의 클래스 로더이다.

  • 즉, 클래스 로더는 런타임 중에 JVM의 메소드 영역에 동적으로 Java 클래스(.class)를 로드하는 역할을 한다.

  • 클래스 로더는 로딩(Loading), 링킹(Linking), 초기화(Initializing) 단계로 나눠져있다.

로딩(Loading)

  • 자바 바이트 코드(.class)를 메소드 영역에 저장한다.

  • 각 자바 바이트 코드(.class)는 JVM에 의해 메소드 영역에 다음 정보들을 저장한다.(로드된 클래스를 비롯한 그의 부모 클래스의 정보, 클래스 파일과 Class, Interface, Enum의 관련 여부, 변수나 메소드 등의 정보)

링킹(Linking)

  • 검증(Verifying) : 읽어 들인 클래스가 자바 언어 명세 및 JVM 명세에 명시된 대로 잘 구성되어 있는지 검사한다.

  • 준비(Preparing) : 클래스 및 인터페이스에 필요한 static field 메모리를 할당하고, 이를 기본값으로 초기화를 한다. 기본값으로 초기화된 static field 값들은 뒤의 Initialization 과정에서 코드에 작성한 초기값으로 변경이 된다. 이 때문에 JVM 에 탑재된 클래스 파일의 코드를 작동시키지는 않는다.

  • 분석(Resolution) : Symbolic Reference 값을 JVM 의 메모리 구성 요소인 Method Area 의 런타임 환경 풀을 통하여 Direct Reference 라는 메모리 주소 값으로 바꿔준다. 해당 단계의 영향을 받는 JVM Instruction 요소는 new 및 instanceof 가 있다.

초기화(Initializing)

  • Linking 과정을 거치면 Initialization 단계에서는 클래스 파일의 코드를 읽게 된다. Java 코드에서의 class 와 interface 의 값들을 지정한 값들로 초기화 및 초기화 메서드를 실행시켜준다. 이때, JVM 은 멀티 쓰레딩으로 작동을 하며, 같은 시간에 한 번에 초기화를 하는 경우가 있기 때문에 초기화 단계에서도 동시성을 고려해주어야 한다. Class Loader 를 통한 클래스 탑재 과정이 끝나면 본격적으로 JVM 에서 클래스 파일을 구동시킬 준비가 끝나게 된다.

JIT 컴파일러

  • 전통적인 입장에서 컴퓨터 프로그램을 만드는 방법은 두 가지가 있는데, 인터프리트 방식과 정적 컴파일 방식으로 나눌 수 있다. 이 중 인터프리트 방식은 실행 중 프로그래밍 언어를 읽어가면서 해당 기능에 대응하는 기계어 코드를 실행하며, 반면 정적 컴파일은 실행하기 전에 프로그램 코드를 기계어로 번역한다.

  • JIT 컴파일러는 두 가지의 방식을 혼합한 방식으로 생각할 수 있는데, 실행 시점에서 인터프리트 방식으로 기계어 코드를 생성하면서 그 코드를 캐싱하여, 같은 함수가 여러 번 불릴 때 매번 기계어 코드를 생성하는 것을 방지한다.

  • JIT 컴파일러가 컴파일하는 조건은 얼마나 자주 코드가 실행됐는가 이다. 일정한 횟수만큼 실행되고 나면 컴파일 임계치에 도달하고 컴파일러는 컴파일하기에 충분한 정보가 쌓였다고 생각한다.

  • 임계치는 메서드가 호출된 횟수, 메서드의 루프를 빠져나오기까지 돈 횟수 이 두 개를 기반으로 한다. 이 두 수의 합계를 확인하고 메서드가 컴파일될 자격이 있는지 여부를 결정한다. 자격이 있다면 메서드는 컴파일되기 위해 큐에서 대기한다. 이후 메서드들은 컴파일 스레드에 의해 컴파일된다.

  • 아주 오랫동안 돌아가는 루프 문의 카운터가 임계치를 넘어가면 해당 루프는 컴파일 대상이 된다. JVM은 루프를 위한 코드의 컴파일이 끝나면 루프가 다시 반복될 때는 코드를 컴파일된 코드로 교체하고 더 빠르게 실행된다. 이 교체 과정을 "스택 상의 교체(on-stack replacement, ORS)"라고 부른다.

profile
Just Do It

2개의 댓글

comment-user-thumbnail
2023년 8월 14일

훌륭한 글 감사드립니다.

1개의 답글