July
13th,
2021
HotSpot VM은 어떻게 구성되어 있을까?
HotSpot이란?
- 자바에서 한 때 성능 개선을 위해 Jut In Time(JIT) 컴파일러를 만들었고, 이름을 HotSpot으로 지었다.
- HotSpot은 자바 1.3부터 기본 VM으로 사용되어 왔기 때문에, 지금 운영되고 있는 대부분의 시스템들은 모두 HotSpot 기반의 VM이라고 생각하면 된다.
- HotSpot VM은 세가지 주요 컴포넌트로 되어 있다.
- VM(Virtual Machine) 런타임
- JIT(Just In Time) 컴파일러
- 메모리 관리자
- HotSpotVM은 GC방식과, JIT 컴파일러가 HotSpot VM 런타임에 레고처럼 끼워 맞춰진다고 볼 수 있다.
- 이를 위해 VM 런타임은 JIT컴파일러용 API와 가비지 컬렉터용 API를 제공한다.
- 그 외에도, JVM을 시작하는 런처와 스레드 관리, JNI등도 VM 런타임에서 제공한다.
JIT Optimizer란 무엇인가?
- 우선 JIT Optimizer에 대해 알아보기 전에, 기초적인 지식에 대해 알아보자.
- 컴파일 : 상위 레벨의 언어로 만들어진 기계에 의존적인 코드로 변환하는 것
- 자바는 javac라는 컴파일러를 사용해, 소스코드를 바이트 코드로 된 class파일로 변환한다. 그렇기 때문에 JVM은 항상 바이트 코드로 시작하며, 동적으로 기계에 의존적인 코드로 변환해준다.
- 초기 JVM 구동시 모든 코드는 인터프리터에 의해 시작되고, 해당 코드가 충분히 많이 사용될 경우 JIT 방식으로 컴파일할 대상이 된다.
- 각 메서드에 있는 카운터를 통해 통제된다.
JVM의 시작 절차
java 명령으로 HelloWorld라는 클래스를 실행하면 어떤 단계로 수행될까? 정ㄹ해보면 다음과 같다.
- java 명령어 줄에 있는 옵션 파싱
- 자바 힙 크기 할당 및 JIT 컴파일러 타입 지정
- CLASSPATH, LD_LIBRARY_PATH같은 환경 변수 지정
- 자바의 Main 클래스가 지정되어 있지 않을 경우 Jar 파일의 manifest 파일에서 Main 클래스 확인
- JNI의 표준 API인 JNI_CreateJavaVM을 사용해 새로 생성한 non-primordial이라는 스레드에서 HotSpot VM 생성
- HotSpot VM 생성후 초기와 완료시 Main 클래스가 로딩된 런처에서는 main() 메서드의 속성정보를 읽는다.
- CallStatisVoidMethod라는 네이티브 인터페이스를 불러 main() 메서드 실행
JVM의 종료 절차
- HotSpot VM이 작동중인 상황에서는 단 하나의 데몬이 아닌 스레드(nondaemon thread, OS가 사용하지 않는, 애플리케이션 단에서 수행되는 스레드)가 수행될 때 까지 대기한다.
- Shutdown 클래스의 shutdown() 메서드가 수행된다.
- HotSpot VM 레벨의 shutdown hook을 수행함으로써 HotSpot VM의 종료를 준비한다.
- HotSpot의 JavaThread::exit() 메서드를 호출해 JNI 처리 블록을 해제한다.
- HotSpot VM 스레드를 종료한다.
- JNI, HotSpot VM, JVMTI barrier에 있는 추적 기능을 종료시킨다.
- 네이티브 스레드에서 수행하고 있는 스레드를 위해 HotSpot의 “vm exited” 값을 설정한다.
- 현재 스레드를 삭제한다.
- 입출력 스트림을 삭제하고, PerfMemory 리소스 연결을 해제한다. 10.JVM 종료를 호출한 호출자로 복귀한다.
클래스 로딩 절차
- 주어진 클래스의 이름으로 클래스 패스에 있는 바이너리로 된 자바 클래스를 찾는다.
- 자바 클래스를 정의한다.
- 해당 클래스를 나타내는 java.lang 패키지의 Class 클래스의 객체를 생성한다.
- 링크 작업이 수행된다.
- 클래스의 초기화가 진행되며, 클래스의 static 블록과 static 필드가 가장 먼저 초기화 된다.
정리하자면, loading -> linking -> initializing 순으로 실행된다고 볼 수 있다.