ClassLoader
자바 소스 코드가 컴파일된 클래스 파일(.class)은 JVM에 탑재 되어 실행되면서 자바 프로그램이 실행된다. 그러면 어떻게 클래스 파일을 JVM에 탑재시킬까? 자바의 기본적인 클래스 파일은 $JAVA_HOME 내부 경로에 있으며 자신이 만든, 또는 다른 사람이 만든 클래스 파일은 여러 디렉터리에 흩어져 있다. 흩어져 있는 클래스 파일을 찾아 JVM에 탑재(load) 시키는 역할을 하는 것이 ClassLoader이다.
ClassLoader는 크게 Loading, Linking, Initialization 3가지 단계로 클래스 파일을 JVM에 탑재한다. Loading은 클래스 파일을 JVM에 탑재하는 과정, Linking은 클래스 파일을 검증하고 기본 값으로 초기화하는 과정, Initialization은 static field의 값을 정의한 값으로 초기화하는 과정이다.
Loading
로딩하는 클래스 파일의 수준에 따라 3개의 class loader으로 분류 된다.
- 부트스트랩 클래스 로더 (Bootstrap Class loader) : 모든 클래스로더의 부모가 되는 클래스로더이다. 자바 클래스 로더와 기본적인 클래스만을 로드한다. (java.lang.Object, Class, ClassLoader ···) Java 8에서는 rt.jar 파일에서 로드하지만 Java 9 이후 /lib에 모듈화되어 포함되었다.
- 확장 클래스 로더 (Extension Class loader) : 확장 클래스를 로드한다. java.ext.dirs 환경 변수에 설정된 디렉토리의 클래스 파일을 로드하지만 이 값이 설정되어 있지 않은 경우 ${JAVA_HOME}/jre/lib/ext 에 있는 클래스 파일을 로드한다. Java 8에서는 URL ClassLoader를 상속하며, jre/lib/ext 내 모든 클래스를 로드한다. Java 9 이후 Platform Loader로 변경되었으며, URLClassLoader가 아닌 BuiltinClassLoader를 상속한다.
- 시스템 클래스 로더 (System Class loader) : classpath에 있는 클래스를 로드한다. 즉 개발자가 만든 클래스 파일을 로드한다.
classpath는 .class 파일이 포함된 디렉토리와 파일을 콜론(:)으로 구분한 목록이다. classpath에는 클래스 파일이 포함된 디렉터리, 여러 클래스 파일이 압축된 zip, jar 파일의 경로가 지정된다. classpath에 경로를 지정하려면 환경 변수 CLASSPATH 또는 java -classpath 플래그로 경로를 지정하면 된다. 실제로 인텔리제이에서 자바 프로그램을 run하면 javac로 자바 소스 코드를 컴파일 한후 아래의 명령이 실행된다.
"C:\Program Files\Java\jdk1.8.0_341\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2022.2\lib\idea_rt.jar=57129:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2022.2\bin"
-Dfile.encoding=UTF-8
-classpath "C:\Program Files\Java\jdk1.8.0_341\jre\lib\charsets.jar;
C:\Program Files\Java\jdk1.8.0_341\jre\lib\deploy.jar;
C:\Program Files\Java\jdk1.8.0_341\jre\lib\ext\access-bridge-64.jar;
C:\Program Files\Java\jdk1.8.0_341\jre\lib\ext\cldrdata.jar;
(생략)
C:\Program Files\Java\jdk1.8.0_341\jre\lib\plugin.jar;
C:\Program Files\Java\jdk1.8.0_341\jre\lib\resources.jar;
C:\Program Files\Java\jdk1.8.0_341\jre\lib\rt.jar;
C:\Users\GUNJOON\Desktop\WorkSpace\Java\Algorithm\out\production\Algorithm" Main
또한 java -verbose 명령어로 클래스 로드 과정을 추적할 수 있다. 간단한 프로그램을 실행하더라도 정말 많은 클래스가 로드 되는걸 확인할 수 있으며 내가 만든 UserClass도 로드 되는걸 확인할 수 있다.
java -verbose Main
[Opened C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
[Loaded java.lang.Object from C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
[Loaded java.io.Serializable from C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
[Loaded java.lang.Comparable from C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
(생략)
[Loaded java.lang.Void from C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
[Loaded java.lang.Package from C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
[Loaded UserPackage.UserClass from file:/C:/Users/GUNJOON/Desktop/WorkSpace/Java/Algorithm/out/production/Algorithm/]
[Loaded java.util.Queue from C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
[Loaded java.util.Deque from C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
[Loaded java.util.AbstractSequentialList from C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
[Loaded java.util.LinkedList from C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
[Loaded jdk.internal.misc.TerminatingThreadLocal$1 from C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
[Loaded java.lang.Shutdown from C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
[Loaded java.lang.Shutdown$Lock from C:\Program Files\Java\jre1.8.0_341\lib\rt.jar]
Linking
로드된 클래스 파일을 검증하고 기본 값으로 초기화하는 과정이다. Linking은 Verification, Preparation, Resolution이라는 세 가지 단계로 이루어져 있다.
- Verification : 클래스 파일이 유효한지를 확인하는 과정이다. 클래스 파일이 JVM의 구동 조건 대로 구현되지 않았을 경우 VerifyError를 던지게 된다.
- Preparation : static field 메모리를 할당하고 이를 기본값으로 초기화한다. 기본값으로 초기화된 static field의 값은 뒤의 Initialization 과정에서 코드에 정의한 값으로 초기화 된다.
- Resolution : Symbolic Reference 값을 JVM 의 메모리 구성 요소인 Method Area 의 런타임 환경 풀을 통하여 Direct Reference 라는 메모리 주소 값으로 바꾼다. 해당 단계의 영향을 받는 JVM Instruction 요소는 new 및 instanceof 가 있다.
Initialization
static field 값이 코드에 정의한 값으로 초기화 된다.
'Java > Basic' 카테고리의 다른 글
Java 람다식 (0) | 2023.04.05 |
---|---|
Java 익명 클래스 (0) | 2023.04.04 |
Regex (0) | 2023.01.23 |
Java 정렬 (0) | 2022.09.07 |
[JVM - 1] JVM, JRE, JDK (0) | 2022.08.17 |