프로그래밍시니어 자바 백엔드 개발자

자바의 클래스 로딩 메커니즘은 어떻게 작동하며, 클래스 로더의 종류는 무엇이며 잘못 사용했을 때 발생할 수 있는 문제는 무엇입니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

자바에서는 클래스를 특별한 객체인 클래스 로더(class loaders)를 통해 메모리에 로드합니다. 각 클래스 로더는 고유한 클래스 가시성 공간을 형성합니다.

클래스 로더의 종류:

  1. 부트스트랩 클래스 로더(Bootstrap ClassLoader) — 기본 JDK 클래스를 로드합니다 (예: rt.jar).
  2. 익스텐션 클래스 로더(Extension ClassLoader)$JAVA_HOME/lib/ext에서 확장 클래스를 로드합니다.
  3. 시스템(어플리케이션) 클래스 로더(System (Application) ClassLoader) — 어플리케이션의 classpath에서 클래스를 로드합니다.
  4. 커스텀 클래스 로더(Custom ClassLoader) — 동적 로딩을 위한 사용자 정의 로더입니다.

특징:

  • 클래스는 (class loader, 클래스 이름)의 조합을 기준으로 고유하다고 간주됩니다.
  • 서로 다른 로더에 의해 로드된 동일한 클래스는 다른 것으로 간주됩니다.
  • 클래스 로더는 계층 구조(부모-자식)를 형성합니다.
  • 바이트에서 클래스를 로드할 수 있습니다(defineClass) — 플러그인/JSP 등에서 유용합니다.

트릭 질문.

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의 클래스)에 대한 접근을 잃었습니다. 결과적으로 새로운 모듈이 표준 자바 클래스를 로드할 수 없게 되어 오류가 발생했습니다.