0. 들어가기
JVM의 구조 중 Class Loader에 대해 쉽게 설명해 보자.
2023.08.09 - [개발/Java] - [Java]자바의 JVM에 대해 이해해보자
JVM의 구성요소 중 클래스 로더에 관한 설명이다. JVM의 전체 구조에 관해서는 윗 글을 참고하자.
1. Class Loader(클래스 로더)
클래스 로더는 이름 그대로 컴파일되어 .class인 자바 바이트코드를 JVM이라는 가상 컴퓨터에 올리는 역할을 한다.
그림에서 볼 수 있듯 로딩은 세 가지 페이즈 Loading, Linking, Initialization으로 세부 단계를 나눈다.
1.1 Loading(로딩)
말 그대로 .class파일을 JVM으로 가져오는 것이다(물리적으로는 메인 메모리).
클래스 또는 인터페이스의 바이트코드를 가져와서 원래 클래스, 인터페이스를 생성한다.
세 개의 클래스 로더를 통해 로딩한다. 각각이 무엇인지 알아보자.
상속 관계를 갖는 세 개의 클래스 로더
1. Bootstrap Class Loader(부트스트랩 클래스 로더)
부트스트랩 클래스 로더는 루트 클래스 로더다. 이 또한 클래스이며, 확장 클래스 로더의 부모가 된다.
java.lang, java.net, java.util, java.io 등과 같은 표준 Java 패키지를 로드한다.
이 패키지는 rt.jar 파일 내부에 있다.
다른 핵심 라이브러리들은 $JAVA_HOME/jre/lib에 있다.
2. Extention Class Loader(확장 클래스 로더)
부트스트랩 클래스 로더의 하위 클래스, 애플리케이션 클래스 로더의 상위 클래스이다.
디렉토리에 있는 표준 Java 라이브러리의 확장을 로드한다.
$JAVA_HOME/jre/lib/ext.
3. Application Class Loader(애플리케이션 클래스 로더)
최종 클래스 로더로 확장 클래스 로더의 하위 클래스이다.
클래스 경로에 있는 파일을 로드한다.
클래스 로딩 과정
기본적으로 클래스 경로는 애플리케이션의 현재 디렉토리이다. 내 코드를 최종 로드한다고 보면 되겠다.
-classpath 또는 -cp command line 옵션을 추가하여 클래스 경로를 수정할 수도 있다.
JVM은 ClassLoader.loadClass() method를 사용하여 클래스를 메모리로 로딩한다. fully qualified name을 기반으로 클래스 로드를 시도한다. 클래스 로더가 클래스를 찾을 수 없으면, 일을 자식 클래스 로더에게 위임하는 식으로 넘어간다.
마지막 클래스 로더도 로딩이 불가능하면, NoClassDefFoundError이나 ClassNotFoundException을 throw한다.
1.2 Linking(링킹)
클래스가 메모리에 로드되고 링크 프로세스를 실행한다.
클래스 또는 인터페이스를 링크하는 것은 프로그램의 다른 요소와 의존성들을 결합하는 것을 포함한다.
linking도 세 단계로 나누어 생각할 수 있다.
Lingking의 세 단계
1. Verification
제약조건과 룰을 체크하여 .class 파일의 구조적 정확성을 체크한다.
여기서 통과하지 못하면, VerifyException을 낸다.
예를들어 코드가 Java11로 빌드됐는데, Java8이 깔린 시스템에서 실행하면 fail이 난다.
2. Preparation
다음으로 준비 단계에서는 JVM이 클래스나 인터페이스의 static fields에 메모리를 할당하고, 디폴트 값으로 초기화한다.
예를 들어
private static final boolean enabled = true;
이러한 코드 선언이 있다면, enabled 변수에 메모리를 할당하면서 해당 type의 default 값인 false로 초기화한다.
실제 코드는 true임에도 이 단계에서는 고려되지 않는다.
3. Resolution
이 단계에서 symbolic 참조가 있다면, runtime constant pool에 있는 직접 참조로 대체된다.
예를들어 다른 클래스나 다른 클래스의 상수를 참조할 경우, 직접 참조로 대체된다.
1.3 Initialization(초기화)
여기서는 클래스 또는 인터페이스의 초기화 method인 <clinit> 실행이 포함된다.
1. 클래스의 생성자를 호출하고
2. static 블록을 실행하며
3. 모든 정적 변수에 값이 할당된다.
- 링킹 단계에서 메모리만 할당받고 default로 초기화된 static 변수에 실제 값이 할당된다.
마무리
컴파일 한 Java byte code를 실행했을 때 어떻게 JVM에 올라가는지를 살펴보았다.
아직 안 봤다면 JVM의 전체 구조도 살펴보는 것을 추천한다.
2023.08.09 - [개발/Java] - [Java]자바의 JVM에 대해 이해해보자
[Java]자바의 JVM에 대해 이해해보자
0. 들어가기 2023.05.27 - [개발/Java] - Java에서 컴파일(compile)이란 무엇일까? JVM,JDK,JRE? 바이트코드? 이전에 자바공부를 시작하기 전에 간단하게 코드와 데이터, 자바의 컴파일과 JVM, JDK, JRE, IDE에 대해
pabu.tistory.com
'개발 > Java' 카테고리의 다른 글
[Java]자바의 JVM에 대해 이해해보자 (0) | 2023.08.09 |
---|---|
[Java] Scanner 스캐너는 왜 close()를 해야 할까? (0) | 2023.07.25 |
[Java]자바의 반복문 (0) | 2023.07.21 |
[Java] 자바 조건문: If-else, Switch-case, Switch Expression (0) | 2023.07.21 |
[Java]자바의 연산자 (0) | 2023.07.19 |