
JVM 클래스 로더
JVM 클래스 로더란?
컴파일러를 통해 .class 확장자를 가진 클래스 파일은 여러 디렉터리에 흩어져 있고 기본적인 라이브러리의 클래스 파일들은 $JAVAHOME_ 내부 경로에 위치하는데 각각의 클래스 파일들을 찾아서 런타임 시점에 동적으로 JVM의 메모리에 탑재해주는 역할을 하는것이 JVM의 클래스 로더이다.
- 클래스 로더는 런타임 중에 JVM의 메소드 영역에 동적으로 Java 클래스를 로드한다
- 클래스 로더 동작 과정은 로딩(Loading), 링크(Linking), 초기화(Initialization) 단계로 나뉘어져 있다.
클래스 로더 계층
-
Bootstrap ClassLoader
- 최상위 계층의 ClassLoader, 즉 모든 클래스로더의 부모가 되는 클래스 로더
- rt.jar 를 포함하여, JVM을 구동시키기 위한 가장 필수적인 라이브러리의 클래스들을 JVM에 탑재
- 탑재되는 운영체제에 맞게 네이티브 코드로 작성됨
- $JAVAHOME/jre/lib/ext_ 에 위치
-
Extensions ClassLoader
- BootStrap ClassLoader다음으로 우선순위를 가지는 클래스 로더
- 표준 핵심 Java Class 의 라이브러리들을 JVM 에 탑재하는 역할
-
Application(System) ClassLoader
- ClassPath에 있는 클래스들(개발자들이 자바코드로 작성한 클래스 파일)을 탑재
-
각 계층의 클래스 로더의 구현 구조
static class ExtClassLoader extends URLClassLoader {
}
static class AppClassLoader extends URLClassLoader {
}
public class URLClassLoader extends SecureClassLoader implements Closeable{
}
public class SecureClassLoader extends ClassLoader {
}
public abstract class ClassLoader{
}

클래스 로더의 동작 방식
클래스 로더는 새로운 클래스를 로드해야 할 때, 다음과 같은 방식으로 로드를 수행한다.
- JVM의 메소드 영역에 클래스가 로드되어 있는지 확인한다. 만일 로드되어 있는 경우 해당 클래스를 사용
- 메소드 영역에 클래스가 로드되어 있지 않을 경우, 시스템 클래스 로더에 클래스 로드를 요청
- 시스템 클래스 로더는 확장 클래스 로더에 요청을 위임
- 확장 클래스 로더는 부트스트랩 클래스 로더에 요청을 위임
- 부트스트랩 클래스 로더는 부트스트랩 Classpath(JDK/JRE/LIB)에 해당 클래스가 있는지 확인한다. 클래스가 존재하지 않는 경우 확장 클래스 로더에게 요청을 넘긴다
- 확장 클래스 로더는 확장 Classpath(JDK/JRE/LIB/EXT)에 해당 클래스가 있는지 확인한다. 클래스가 존재하지 않을 경우 시스템 클래스 로더에게 요청을 넘긴다
- 시스템 클래스 로더는 시스템 Classpath에 해당 클래스가 있는지 확인한다. 클래스가 존재하지 않는 경우
ClassNotFoundException을 발생시킨다.
클래스 로더 동작 과정
-
Loading
- 클래스로더의 하위 계층으로 요청이 상위 계층으로 위임되고 클래스 존재 유무에 따라 다시 하위 계층으로 요청을 넘긴다.
- 하위 클래스 로더가 로드한 클래스 파일은 상위 클래스 로더가 로드한 클래스 파일을 볼 수 있음(Visibility)
- JVM에 탑재된 클래스 파일은 종료될 때 까지 JVM에서 제거되지 않는다.
-
Linking
Linking 은 로드된 클래스 파일들을 검증하고, 사용할 수 있게 준비하는 과정을 의미
- Verification : 클래스 파일이 유효한지를 확인하는 과정
- Preparation : 클래스 및 인터페이스 static filed 메모리 할당 및 기본값으로 초기화
- Resolution : 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체한다.
-
Initialization
- 클래스 파일의 코드를 읽고 static 필드의 값을 초기화, 초기화 매서드를 실행시킨다
- 멀티쓰레딩으로 동작하기 때문에 초기화 단계에서 동시성 문제를 고려해야한다
클래스 로더가 지켜야 할 세 가지 원칙
- 위임 원칙 클래스 로더는 클래스 또는 리소스를 찾기 위해 요청을 받았을 때, 상위 클래스 로더에게 책임을 위임하는 위임 모델을 따른다.
- 가시 범위 원칙 하위 클래스 로더는 상위 클래스 로더가 로드한 클래스를 볼 수 있지만, 반대로 상위 클래스 로더는 하위 클래스 로더가 로드한 클래스를 알 수 없다.
- 유일성의 원칙
- 하위 클래스 로더가 상위 클래스 로더에게 로드한 클래스를 다시 로드하지 않아야 한다는 원칙이다.
- 위임 원칙에 의해서 위쪽으로 책임을 위임하기 때문에 고유한 클래스를 보장할 수 있다.
클래스 로딩 & 초기화시점
- 클래스 로딩 시점
- 클래스의 인스턴스 생성
- 클래스의 정적 변수 사용 (final 키워드 X)
- 클래스의 정적 메소드 호출
- 클래스가 로딩 X
- 클래스에 접근하지 않을 때
- 클래스의 정적 변수 사용 (final 키워드 O)
- 초기화 시점
- 클래스의 인스턴스 생성
- 클래스의 정적 변수 사용 (final 키워드 X)
- 클래스의 정적 메소드 호출