자바에서는 클래스를 특별한 객체인 클래스 로더(class loaders)를 통해 메모리에 로드합니다. 각 클래스 로더는 고유한 클래스 가시성 공간을 형성합니다.
클래스 로더의 종류:
$JAVA_HOME/lib/ext에서 확장 클래스를 로드합니다.특징:
JVM 프로세스에 동일한 클래스의 여러 버전을 로드할 수 있으며, 어떻게 합니까?
답변: 가능합니다. 서로 다른 클래스 로더를 사용하면 됩니다. 동일한 FQDN을 가진 클래스는 서로 다른 로더에 의해 로드되면 JVM에서 서로 다른 타입으로 간주됩니다.
예시:
ClassLoader loader1 = new URLClassLoader(new URL[]{...}); ClassLoader loader2 = new URLClassLoader(new URL[]{...}); Class clazz1 = loader1.loadClass("com.example.MyClass"); Class clazz2 = loader2.loadClass("com.example.MyClass"); System.out.println(clazz1 == clazz2); // false
이야기
대규모 서버 시스템에서는 플러그인을 사용했으며, 각 플러그인은 별도의 커스텀 클래스 로더를 통해 연결되었습니다. 플러그인은 공유 인터페이스를 통해 객체를 교환했으며, 이 인터페이스 또한 자신만의 클래스 로더로 로드되었습니다. 그 결과, 플러그인에서의 'PluginApi' 인터페이스와 기본 시스템에서의 인터페이스는 서로 다른 타입으로 간주되어 ClassCastException이 발생했습니다.
이야기
커스텀 클래스 로더를 통해 서블릿을 "핫" 리로드하려고 시도했지만, 메모리 누수로 이어졌습니다. 이전 클래스가 메모리에서 해제되지 않았고, 정적 변수 중 어딘가에서 참조가 남아 있었습니다. 이로 인해 PermGen이 빠르게 넘쳤습니다.
이야기
동적 모듈 로딩을 지원하는 제품이 시스템 클래스 로더를 암묵적으로 사용하고 있었으며, 개발자가 실수로 부모를 변경하여 기본 클래스(예: JDK의 클래스)에 대한 접근을 잃었습니다. 결과적으로 새로운 모듈이 표준 자바 클래스를 로드할 수 없게 되어 오류가 발생했습니다.