kok202
JVM 의 실행, 종료, 클래스 로더, 아키텍쳐

2020. 4. 23. 02:31[정리] 기능별 개념 정리/JVM

JVM 실행 절차

  1. Java 실행 옵션을 파싱한다.
  2. 힙크기를 할당한다.
  3. JIT 컴파일러 타입을 지정한다.
  4. 환경변수를 지정한다. (CLASSPATH, LD_LIBRARY_PATH)
  5. Main 클래스를 확인한다.
  6. HotSpot VM 을 생성한다.
    1. JNI_CreateJavaVM 가 HotSpot VM을 생성된다.
    2. JNI_CreateJavaVM 는 동시 호출이 불가능하다.
    3. JNI_CreateJavaVM 가 non_primordial 스레드에서 HotSpot VM을 생성한다.
    4. JNI 호환성을 점검한다.
    5. GC 준비를 한다.
    6. 각종 초기화를 한다.
      1. OS 모듈을 초기화한다. (Pid, 랜덤 시드)
      2. 커맨드 라인 변수를 파싱한다.
      3. 표준 자바 시스템 속성을 초기화된다.
      4. 동기화, 메모리같은 모듈이 초기화된다.
      5. libjava 같은 라이브러리들이 로드된다.
      6. 시그널 처리기가 초기화 된다.
      7. 스레드 라이브러리가 초기화 된다.
      8. output 스트림이 초기화된다.
      9. JVM 모니터링 에이전트 라이브러리 설정을 초기화한다.
      10. 스레드 상태를 초기화한다.
      11. HotSpotVM 의 글로벌 데이터를 초기화한다.
      12. HotSpotVM 이 스레드를 생성할 수 있는 상태가된다.
      13. Main 스레드가 생성되어 현재 OS 스레드에 붙는다. 하지만 아직 스레드 목록에 추가되지는 않는다.
      14. 자바 레벨의 동기화가 초기화, 활성화된다.
      15. 글로벌 데이터 구조 집합이 초기화 된다.
      16. Main 스레드가 스레드 목록에 추가된다.
      17. java.lang 패키지의 클래스들이 로딩되고 초기화된다.
      18. JIT 컴파일러가 초기화된다.
      19. HotSpotVM 의 시그널 핸들러 스레드가 시작된다.
      20. HotSpotVM 의 컴파일 브로커 스레드가 시작된다.
      21. HotSpotVM 의 전체 기능이 동작한다.
      22. JNIEnv 가 시작된다.
  7. main() 메소드의 속성을 읽는다.
  8. main() 메소드를 수행한다.

 

 

 

JVM 종료 절차

JVM 을 정상 종료하지 않고 kill-9 같은 명령을 사용하면 이 절차를 따르지 않는다.

JVM 이 정상 종료 되는 상황은 시작 할 때 오류가 있거나 심각한 에러가 있을 경우이다.

JVM 이 정상 종료 될 때 HotSpotVM 이 DestroyJavaVM  이라는 메소드를 호출한다.

  1. Java.lang 패키지의 Shutdown.shutdown() 이 수행된다.
  2. 자바 레벨의 shutdown hook 이 발생한다. 
  3. 자바 객체의 finalizer 가 수행된다.
  4. JVM_OnExit() 메소드에 의해 HotSpotVM 의 종료를 준비한다.
  5. HotSpotVM 의 스레드가 종료된다.
  6. Signal 스레드가 종료된다.
  7. JavaThread.exit() 메소드에 의해 JNI처리 블록을 해제한다.
  8. HotSpotVM 스레드를 종료한다.
  9. JIT 컴파일러 스레드를 중지한다.
  10. Tracing 기능을 종료한다.
  11. HotSpot 의 “VM Exit” 값을 설정한다.
  12. 현재 스레드를 삭제한다.
  13. 입출력 스트림을 삭제한다.
  14. PerfMemory 연결을 해제한다.

 

 

 

클래스 로더

JRE 에는 클래스를 읽고 로딩하기 위해 클래스 로더라는 것들이 존재한다.

클래스 로더들은 계층 구조를 이루며 다른 클래스 로더에 클래스 로딩을 위임 할 수도 있다.

클래스 로더는 크게 4가지로 분류된다.

  1. 기본 클래스 로더
    기본 클래스 로더를 시스템 클래스 로더라고 부른다.
    기본 클래스 로더는 main 클래스와 클래스 패스에 있는 클래드들의 클래스 로더이다.
  2. 부트스트랩 클래스 로더
    <JAVA_HOME>/jre/lib 에있는 핵심 자바 라이브러리들을 불러들인다
    rt.jar (JavaSE 클래스 라이브러리를 포함) 여기에 속한다.
  3. 확장 클래스 로더
    <JAVA_HOME>/jre/lib/ext 또는 java.ext.dirs 시스템 속성에 지정된 기타 디렉터리)에 코드를 로드한다.
  4. 사용자 지정 클래스 로더
    자바 클래스 로더는 자바로 작성된다. 그러므로 사용자가 클래스 로더를 만들 수도 있다.

 

 

 

클래스 메타데이터

클래스를 로딩하면 클래스에 instanceKlass 와 arrayKlass 라는 형식이 Perm  영역에 생성된다.

instanceKlass 는 클래스의 정보를 포함하는 java.lang.Class 클래스의 인스턴스다.

HotSpot VM 은 KlassOop 를 이용하여 instanceKlass 에 접근한다. (Ordinary Object Pointer)

 

 

 

클래스 로딩 추적, 관리

HotSpotVM은 클래스 로딩을 추적, 관리하기 위해 아래 3개의 테이블을 관리한다.

  • SystemDictionary : 로드된 클래스, 클래스 이름, 초기화한 클래스 로더의 정보등을 갖는다.
  • PlaceholderTable : 로딩된 클래스들에 대한 정보를 관리한다.
  • LoaderConstraintTable : 타입 체크시 제약 조건 추정 용도로 사용된다.

 

 

 

JVM 의 클래스 로딩 절차

  1. 클래스를 찾는다.
  2. 클래스를 정의한다.
  3. 클래스를 java.lang 패키지의 Class 클래스의 객체로 생성한다.
  4. 링크 작업을 수행한다.
  5. 클래스에 Static 필드를 생성, 초기화 한다.
  6. 클래스에 메소드 테이블을 할당한다.
  7. 클래스 초기화를 한다.

간단하게 그냥 Loading -> Linking -> Initializing 과정을 거친다고 기억하면 된다.

 

 

 

JVM 의 예외 처리

JVM 은 에러가 생겼을 때 Exception 이라는 시그널로 처리한다.

JVM 에서 예외가 던져졌다는 것을 알아차리면 해당 예외를 처리하는 가장 가까운 핸들러를 찾는다.

이 때 사용되는 것이 HotSpotVM 런타임 시스템이다.

현재 실행 중인 메소드에서 핸들러를 찾지 못할 경우 스택 프레임을 통해서 이전 프레임에서 찾는다.

 

 

 

JVM 아키텍쳐

  • 스택 : 스레드가 시작할 때 생기는 영역, 메소드가 호출 되는 정보인 프레임이 저장된다. 
  • PC 레지스터 : 스레드가 어디까지 읽었는지 를 나타내는 Program counter 
  • 네이티브 메소드 스택 : 스레드가 자바 코드가 아닌 다른 외부 코드 (ex. C) 를 실행할 때 가지는 스택 정보
  • 힙 : 여러 JVM 스레드가 공유한다. 객체 레벨의 정보가 저장된다. 객체, 배열과 같은 메모리가 쌓이는 곳이며 GC 의 대상이 된다.
  • 메소드 : 모든 JVM 스레드가 공유한다. 클래스 레벨의 정보가 저장된다. 런타임 상수, 메소드 데이터, 메소드와 생성자 코드가 있다.

 

 

 

'[정리] 기능별 개념 정리 > JVM' 카테고리의 다른 글

GC  (0) 2020.04.25
JIT 컴파일러  (0) 2020.04.22
Garbage collection 요약  (0) 2020.03.17