* JVM 실행 절차
1. java 명령어 줄에 있는 옵션 파싱
: 일부 명령은 자바 실행 프로그램에서 적절한 JIT 컴파일러를 선택하는 등의 작업을 하기 위해서 사용하고, 다른 명령들은 HotSpot VM 에 전달
2. 자바 Heap 크기 할당 및 JIT 컴파일러 타입 지정 (명령줄에 지정되지 않았을 경우)
: 메모리 크기나 JIT 컴파일러 종류가 명시적으로 지정되지 않은 경우에 시스템의 상황에 맞게 선정
3. CLASSPATH 와 LD_LIBRARY_PATH 같은 환경 변수를 지정
4. 자바의 Main Class 가 지정되지 않았으면, jar 파일의 manifest 파일에서 Main 클래스를 확인
5. JNI 의 표준 API 인 JNI_CreateJavaVM 을 사용하여 새로 생성한 non-primordial 이라는 스레드에서 HotSpot VM 을 생성
1) JNI_CreateJavaVM 은 동시에 2개의 스레드에서 호출할 수 없고, 오직 하나의 HotSpot VM 인스턴스가 프로세스 내에서 생성될 수 있도록 보장
(HotSpot VM 이 정적인 데이터 구조를 생성하기 때문에 다시 초기화는 불가능하기 때문에 오직 하나만 프로세스에서 생성될 수 있다)
2) JNI 버전이 호환성이 있는지 점검하고, GC 로깅을 위해 준비
3) OS 모듈들을 초기화
4) 커맨드 라인 변수와 속성드이 JNI_CreateJavaVM 변수에 전달되고, 나중에 사용하기 위해서 Parsing 한 후 보관
5) 표준 자바 시스템 속성을 초기화
6) 동기화, 메모리, safepoint 페이지와 같은 모듈들을 초기화
7) libzip, libhpi, libjava, libthread 와 같은 라이브러리 로드
8) 시그널 처리기 초기화 및 설정
9) 스레드 라이브러리 초기화
10) Output Stream 로거 초기화
11) JVM 모니터링을 위한 Agent Library 가 설정되어 있으면 초기화 및 실행
12) 스레드 처리를 위해서 필요한 스레드 상태와 스레드 로컬 저장소 초기화
13) HotSpot VM 의 글로벌 데이터 들이 초기화
(Event Log, OS 동기화, 성능 통계 메모리, 메모리 할당자 등이 있음)
14) HotSpot VM 에서 스레드 생성할 수 있는 상태가 됨
(Main Thread 가 생성되고 현재 OS 스레드에 붙는다)
15) 자바 레벨의 동기화가 초기화 및 활성화 됨
16) 부트 클래스로더, 코드 캐시, 인터프리터, JIT 컴파일러, JNI, 시스템 Dictionary, '글로벌 데이터' 구조의 집합인 universe 등이 초기화 됨
17) 스레드 목록에 자바 Main 스레드가 추가되고, universe 상태를 점검
(HotSpot VM Thread 가 생성되고, 현재 상태를 JVMTI에 전달)
18) java.lang 패키지에 있는 String, System, Thread, ThreadGroup, Class 클래스와 하위 패키지에 있는 Method, Finalize 클래스 등이 로딩됨
19) 시그널 핸들러 스레드가 시작되고, JIT 컴파일러가 초기화되며, HotSpot 컴파일 브로커 스레드가 시작됨
(이 때부터, HotSpot VM 전체 기능이 동작됨)
20) JNIEnv 가 시작되며, 새로운 JNI 요청을 처리할 준비가 되었음을 호출자에게 알림
6. HotSpot VM 이 생성되고 초기화되면, Main 클래스가 로딩된 런처에서는 main() 메서드의 속성 정보를 읽는다
7. CallStaticVoidMethod 는 네이티브 인터페이스를 불러 HotSpot VM 에 있는 main() 메서드가 수행
* JVM 종료 절차
> HotSpot VM 의 종료는 DestroyJavaVM 메서드의 종료 절차를 따름
1. HotSpot VM 이 작동중인 상황에서는 Non-daemon Thread 가 수행될 때 까지 대기한다
2. java.lang 패키지에 있는 Shutdown 클래스의 shutdown() 메서드가 수행됨
(자바 레벨의 shutdown hook 이 수행되고, finalization-on-exit 라는 값이 true 인 경우에 자바 객체 finalizer 를 수행)
3. HotSpot VM 의 profiler, stat sampler, watcher, garbage collector 스레드를 종료시킴
(종료가 완료되면 JVMTI 를 비활성화하며, Signal 스레드를 종료시킴)
4. JavaThread.exit() 메서드를 호출하여 JNI 처리 블록을 해제하고, guard pages, 스레드들을 삭제함
(이후로, 자바 코드를 실행하지 못한다)
5. HotSpot VM 스레드를 종료
(남아있는 HotSpot VM 스레드들을 safepoint 로 옮기고, JIT 컴파일러 스레드들을 중지시킴)
6. JNI, HotSot VM, JVMTI barrier에 있는 추적 기능을 종료
7. 네이티브 스레드에서 수행하고 있는 스레드들을 위해 'vmexited' 값을 설정
8. 현재 스레드를 삭제
9. 입출력 스트림을 삭제하고, PerfMemory 리소스 연결을 해제
10. JVM 종료를 호출한 호출자로 복귀
* JVM 에서 예외처리 과정
1. 현재 메서드에서 예외를 처리하는 핸들러를 찾는다
2. 찾지 못한 경우에는 현재 수행되는 스택 프레임을 통해서 이전 프레임을 통해 핸들러를 찾는다
3. HotSpot VM 수행 상태가 변경되며, HotSpot VM 은 핸들러로 이동하고 자바 코드 수행은 계속된다
* JVM 에서 동기화 동작
> Java의 HotSpot VM 은 Java Monitor 를 제공함으로써 Thread 들이 Mutual Exclusion Protocol 에 참여할 수 있도록 돕는다
> Java Monitor 는 Lock/Unlocked 상태 중 하나이며, 한 시점에 단, 하나의 Thread 만 Monitor 를 가질 수 있다. 해당 Thread 만, monitor 에 의해
보호되는 area (synchronized block) 에 들어가며 작업할 수 있다. 이후에, monitor 는 대기중인 다른 thread 에게 넘어간다
> Java 5 부터는 -XX:+UseBiasedLocking 이라는 옵션을 통해서 biased locking 이라는 기능 제공 (Java 15 에서 Deprecated)
: before
- 대부분의 객체들이 하나의 thread 에 의해 locking
: after
- thread 가 자기 자신을 향하여 bias. 즉, cost 가 높은 instruction 재배치를 통해 Lock/Unlock 수행 (Adaptive Spinning 기술 이용)
: 결과적으로, 동기화 작업이 전보다 빨라졌다
> HotSpot VM 에서 대부분의 동기화 작업은 fast-path 코드 작업을 통해 진행하다가, Thread 경합 상황이 발생하면 slow-path 코드 상태로 변환
: fast-path
- JIT Compiler 에서 제공하는 장비에 의존적인 코드로 작성되어 있음
: slow-path
- C++ 코드로 구현되어 있음
'SW > ::: Java' 카테고리의 다른 글
Java GC 및 Memory 설정 (0) | 2020.10.10 |
---|---|
Stream (스트림) (0) | 2020.10.09 |
Thread (쓰레드) (0) | 2020.10.09 |
Collections (List, Set, Queue, Map) (0) | 2020.10.05 |
String (0) | 2020.10.05 |