Java 9 이전에는 확장(Extension) 클래스 로더와 애플리케이션(Application) 클래스 로더가 모두 java.net.URLClassLoader 클래스의 인스턴스였습니다. 그러나 Java 9부터는 클래스 로더의 분류 체계가 변경되어, 기존의 확장 클래스 로더를 대체하는 플랫폼 클래스 로더(Platform Class Loader)가 새롭게 도입되었습니다.
플랫폼 클래스 로더가 도입된 주요 이유는 부트스트랩 클래스 로더(Bootstrap Class Loader)가 로드하는 클래스들이 기본적으로 모든 권한을 가지기 때문입니다. 따라서 일부 플랫폼 관련 클래스들을 부트스트랩이 아닌 별도의 로더로 분리하여 보안과 구조를 개선한 것입니다.
클래스 로더와 함께 모든 모듈 표시하기
아래 예제에서는 ModuleLayer.boot()를 사용하여 부트 레이어에 포함된 모든 모듈을 순회하면서, 각 모듈이 어떤 클래스 로더에 의해 로드되었는지 확인하고 출력합니다. 클래스 로더가 null인 경우 해당 모듈은 부트스트랩 클래스 로더에 의해 로드된 것으로 간주합니다.
예제 코드
import static java.util.Objects.isNull;
public class Java9ClassLoaderTest {
public static void main(String args[]) {
ModuleLayer layer = ModuleLayer.boot();
layer.modules().forEach(module -> {
ClassLoader classLoader = module.getClassLoader();
String classLoaderName = isNull(classLoader) ? "bootstrap" : classLoader.getName();
System.out.println(classLoaderName + ": " + module.getName());
});
}
}실행 결과
app: jdk.internal.ed platform: jdk.scripting.nashorn platform: java.compiler platform: java.security.jgss platform: jdk.plugin.dom bootstrap: jdk.net bootstrap: java.management app: jdk.jdeps platform: javafx.base app: jdk.editpad bootstrap: java.security.sasl platform: java.sql.rowset bootstrap: java.datatransfer app: jdk.compiler platform: java.scripting platform: jdk.naming.dns platform: jdk.crypto.mscapi bootstrap: java.xml platform: jdk.localedata platform: javafx.swing bootstrap: jdk.unsupported platform: jdk.plugin bootstrap: jdk.snmp bootstrap: jdk.naming.rmi app: jdk.internal.le platform: javafx.web platform: jdk.dynalink platform: jdk.accessibility bootstrap: java.rmi platform: jdk.jsobject platform: java.sql app: jdk.attach bootstrap: jdk.management.cmm platform: jdk.security.auth platform: java.xml.crypto bootstrap: jdk.jfr bootstrap: jdk.management.jfr platform: jdk.security.jgss app: jdk.packager.services bootstrap: java.base app: jdk.internal.opt bootstrap: java.prefs bootstrap: java.management.rmi platform: jdk.zipfs platform: java.jnlp app: jdk.packager platform: oracle.net app: jdk.jlink bootstrap: jdk.management.agent bootstrap: java.logging app: jdk.jdi app: jdk.jstatd platform: java.se app: jdk.javadoc platform: jdk.charsets platform: java.smartcardio app: jdk.jconsole bootstrap: jdk.sctp platform: javafx.graphics bootstrap: jdk.management.resource app: jdk.jdwp.agent app: jdk.internal.jvmstat platform: javafx.controls platform: jdk.crypto.cryptoki platform: javafx.media bootstrap: jdk.httpserver platform: oracle.desktop bootstrap: java.naming app: jdk.jshell app: jdk.jartool platform: jdk.deploy bootstrap: java.desktop platform: javafx.fxml bootstrap: java.instrument platform: jdk.crypto.ec bootstrap: jdk.management platform: jdk.xml.dom platform: jdk.javaws
결과 해석
출력 결과를 보면 각 모듈은 세 가지 유형의 클래스 로더 중 하나에 속하는 것을 알 수 있습니다.
- bootstrap: java.base, java.desktop, java.logging 등 JDK의 핵심 기본 모듈들이 여기에 속합니다. getClassLoader()가 null을 반환하므로 코드에서 "bootstrap"으로 표시됩니다.
- platform: java.sql, java.xml.crypto, jdk.localedata 등 플랫폼 클래스 로더가 로드하는 모듈들입니다.
- app: jdk.compiler, jdk.jshell, jdk.jlink 등 애플리케이션 클래스 로더가 로드하는 도구성 모듈들입니다.
이처럼 Java 9의 모듈 시스템(JPMS)에서는 ModuleLayer API를 활용하면 런타임에 어떤 클래스 로더가 어떤 모듈을 담당하는지 쉽게 파악할 수 있습니다.