[JAVA] ClassLoader란, 원칙, 계층구조, 로딩단계
- -
Java ClassLoader에 대한 설명으로 아래의 내용들에 대해 다루어 보도록 하겠습니다.
- ClassLoader 정의
- ClassLoader 원칙 (특징)
- ClassLoader 계층 구조
- ClassLoader 로딩 단계
ClassLoader 정의
ClassLoader는 JVM의 구성요소 중 하나로,
'.class' 바이트 코드를 읽어 들여 class 객체를 생성하는 역할을 담당한다.
즉, 클래스가 요청될 때 class파일로부터 바이트 코드를 읽어 메모리로 로딩하는 역할
자바 클래스들은 한 번에 모든 클래스가 메모리에 올라가지 않는다.
각 클래스들은 필요할 때 애플리케이션에 올라가게 되며, 이 작업을 클래스로더가 해주게 된다.
예를 들어 간단한 Class의 main문을 실행할때, load 되는 class들을 확인해보자
java -verbose:class 옵션을 통해 확인 가능하다
public class HelloApp {
public static void main(String argv[]) {
System.out.println("Aloha! Hello and Bye");
}
}
prmpt>java -verbose:class HelloApp
[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]
ClassLoader의 특징 및 원칙
ClassLoader에 대해 찾아보면 3가지 원칙에 대해서 나온다.
- Delegation
- 어떠한 클래스 파일을 로딩할 때, 해당 로딩 요청이 부모 클래스 로더들로 거슬러 올라가 BootstrapClassLoader(최상위 ClassLoader)에 다다른 후 그 밑으로 로딩 요청을 수행
- Visibility
- 상위 Class Loader를 먼저 참조하는것에 이어서, Class Loader는 일종의 scope rule을 제공하는데,
Child Class Loader는 Parent Class Loader의 Class를 Delegation load request를 이용하여 찾을 수 있지만,
그 반대로 Parent가 Child가 Loading한 Class를 사용할 수는 없다.
- 상위 Class Loader를 먼저 참조하는것에 이어서, Class Loader는 일종의 scope rule을 제공하는데,
- Uniqueness
- 하위 클래스로더는 상위 클래스로더가 로딩한 클래스를 다시 로딩하지 않게 해서
로딩된 클래스의 유일성을 보장하는 것이다.
유일성을 식별하는 기준은 클래스의 binary name
- 하위 클래스로더는 상위 클래스로더가 로딩한 클래스를 다시 로딩하지 않게 해서
해당 원칙 이외의 특징
- Unload Impossibility
- 클래스 로더에 의해 로딩된 클래스들은 JVM 상에서 삭제할 수 없다
Unloading 기능을 우회적으로 구현하는 방법은 Class를 로드한 Class Loader 자체를 삭제하고,
새로운 Class Loader를 만들어서 다시 Class를 로드하면, reload 되는 것처럼 작동하는 것이 된다.
- 클래스 로더에 의해 로딩된 클래스들은 JVM 상에서 삭제할 수 없다
- Hierarchical
- 계층적 구조를 가지도록 생성(부모-자식의 관계)
부모 클래스 로더에서 자식 클래스 로더를 가지는 형태
- 계층적 구조를 가지도록 생성(부모-자식의 관계)
ClassLoader 계층 구조
Java ClassLoader의 계층 구조는 Java8 버전과 Java9 버전으로 나뉜다.
각각의 버전별 계층 구조를 설명해 보도록 하겠다
Java8
Bootstrap Class Loader (Primordial Class Loader)
- 자바의 기본 클래스로더 중 최상위 클래스로더로서 parent ClassLoader가 존재하지 않음
- ${JAVA_HOME}/jre/lib/rt.jar에 담긴 JDK 클래스 파일을 로딩(다만, 옵션 -Xbootclasspath 옵션으로 path 수정 가능)
- Native C로 구현돼 있어, String.class.getClassLoader()는 그냥 null을 반환 ( 자바 코드에 의해서 instance화 불가)
Extension Class Loader
- BootstrapClassLoader를 parent로 가지고 있음
- ${JAVA_HOME}/jre/lib/ext 폴더나 java.ext.dirs 환경 변수로 지정된 폴더에 있는 클래스 파일을 로딩
- 자바로 구현되어 있으며, sun.misc.Launcher$ExtClassLoader로 구현되어있고, URLClassLoader를 상속
- 사용자의 classpath를 수정하지 않고 확장으로 쉽게 갈 수 있는 기능을 제공
System Class Loader (Application Class Loader)
- 자바의 -classpath(또는 -cp) 옵션이나, jar 파일 안에 있는 Manifest 파일의 Class-Path 속성 값으로 지정된 폴더에 있는 클래스 로딩
- 개발자가 애플리케이션 구동을 위해 직접 작성한 대부분의 클래스는 여기서 로딩됨
- ClassLoader.getSystemClassLoader()를 통해서 얻을 수 있음
Java9
Java9에서는 모듈 시스템이 도입되어 그에 맞춰 ClassLoader의 범위, 구현 내용이 바뀌었다
Hierarchy는 그대로고, 로드하는 디렉토리의 위치, ClassLoader의 Name정도가 변경되었다
Bootstrap Class Loader
- 모듈화 시스템 도입으로 ${JAVA_HOME}/jre/lib/rt.jar가 없어짐에 따라 로딩하는 클래스의 범위가 전반적으로 축소
- 기존에 parent를 BootstrapClassLoader로 가지고 있던 ClassLoader의 경우 parent에 대한 수정이 필요
Platform Class Loader
- ${JAVA_HOME}/jre/lib/ext 폴더나 java.ext.dirs 환경 변수를 지원하지 않음
- Java SE의 모든 클래스와 JDK-specific run-time 클래스들을 여기서 로딩
- URLClassLoader를 상속받지 않은 ClassLoaders 클래스의 내부 static 클래스로 구현됨
System Class Loader
- classpath, modulepath에 있는 클래스 로딩
ClassLoader 로딩 단계
ClassLoader가 class 파일을 로드하는 단계에 대해서 정리해보도록 하겠다
우선, 크게 3가지 단계로 나눈다
Loading
- .class 파일을 읽어 내용에 따라 적절한 바이너리 데이터를 생성하고, 메서드 영역에 저장
- 메서드 영역: 추후에 jvm의 구성 중, 데이터 영역에서 다룰 내용으로 자세한 설명은 생략
Type정보(class, interface, enum) Method, 변수, FQCN이 저장되는 영역
- 메서드 영역: 추후에 jvm의 구성 중, 데이터 영역에서 다룰 내용으로 자세한 설명은 생략
- 앞에서 설명한, ClassLoader의 계층구조 및 Delegation원칙에 따라서 Root ClassLoader에서부터 load가 필요한 class를 찾는다
- 로딩이 끝나면, Type 정보로 저장된 Class Type Object를 생성하여 Heap 영역에 저장
Linking
로딩 단계로부터 생성된 바이너리 데이터를 JVM의 런타임 데이터로 합치는 과정
이 단계는 3가지 단계로 나뉜다
- Verifying
- .class 파일의 정확성을 보장하기 위한 단계
- 파일이 적절한 포맷인지, 유효한 컴파일러에 의해 생성되었는지를 확인
- 검증이 실패한 경우 런타임 에러 (java.lang.VerifyError) 발생
- Preparing
- 클래스 변수(static 변수)와 기본값에 필요한 메모리를 준비하는 과정
- Resolving
- 심볼릭 메모리 레퍼런스를 메모리 영역에 존재하는 실제 레퍼런스로 교체
- optional 한 단계 ( 설정에 따라서 동작 유무가 정해짐)
Initializing
- 윗 단계인 Linking의 Preparing 단계에서 확보한 메모리 영역에 static 값을 할당
- 클래스의 static 값들을 할당
실제 위의 3가지 단계가 실행되는 java의 ClassLoader API
- loadClass() : 지정된 이름을 가지는 클래스를 로드
- 해당 메서드 내부에서 findLoadedClass() 호출 - 이미 로드된 내역이 있는지 확인
- findClass() : loadClass시 load 된 class가 없을 시, load 하고자 하는 class의 이름으로 클래스 파일 탐색
- defineClass() : 위의 findClass메서드에서 원하는 class파일을 찾은 경우 .class 파일로부터 바이트 배열을 class객체로 변환
참고 내용:)
'Java' 카테고리의 다른 글
[Java] ThreadLocal이란 (0) | 2022.11.24 |
---|---|
[JAVA] JVM 메모리 구조, 데이터 영역 ( Runtime Data Areas) (0) | 2022.08.23 |
[JAVA] 로드타임, 런타임 동적로딩 (Load-Time, Run-Time Dynamic Loading) (0) | 2022.08.10 |
[JAVA] 정적, 동적 바인딩 (Static, Dynamic Binding) (2) | 2022.08.06 |
[Java] Java JVM이란, JVM 구성 (Java Virtual Machine) (0) | 2022.07.28 |
소중한 공감 감사합니다