logo

Java의 클래스로더

자바 클래스로더

Java ClassLoader는 추상 클래스입니다. 그것은 a에 속한다 java.lang 패키지. 다양한 리소스에서 클래스를 로드합니다. Java ClassLoader는 런타임에 클래스를 로드하는 데 사용됩니다. 즉, JVM은 런타임에 연결 프로세스를 수행합니다. 클래스는 필요에 따라 JVM에 로드됩니다. 로드된 클래스가 다른 클래스에 종속되는 경우 해당 클래스도 로드됩니다. 클래스 로드를 요청하면 클래스가 상위 클래스에 위임됩니다. 이러한 방식으로 런타임 환경에서 고유성이 유지됩니다. Java 프로그램을 실행하는 것은 필수적입니다.

암리타 라오 배우
Java의 클래스로더

Java ClassLoader는 세 가지 원칙을 기반으로 합니다. 대표단 , 시계 , 그리고 독창성 .

    위임 원칙:클래스 로딩 요청을 상위 클래스 로더로 전달합니다. 부모가 클래스를 찾거나 로드하지 않는 경우에만 클래스를 로드합니다.가시성 원칙:이는 하위 클래스 로더가 상위 ClassLoader에 의해 로드된 모든 클래스를 볼 수 있도록 합니다. 그러나 상위 클래스 로더는 하위 클래스 로더가 로드한 클래스를 볼 수 없습니다.고유성 원리:클래스를 한 번 로드할 수 있습니다. 이는 위임 원칙에 의해 달성됩니다. 이는 하위 ClassLoader가 상위 클래스에 의해 이미 로드된 클래스를 다시 로드하지 않도록 보장합니다.

클래스로더의 유형

Java에서 모든 ClassLoader에는 클래스 파일을 로드하는 사전 정의된 위치가 있습니다. Java에는 다음과 같은 유형의 ClassLoader가 있습니다.

부트스트랩 클래스 로더: rt.jar 및 기타 핵심 클래스에서 표준 JDK 클래스 파일을 로드합니다. 이는 모든 클래스 로더의 상위입니다. 부모가 없습니다. String.class.getClassLoader()를 호출하면 null이 반환되고 이를 기반으로 하는 모든 코드는 NullPointerException을 발생시킵니다. Primordial ClassLoader라고도 합니다. jre/lib/rt.jar에서 클래스 파일을 로드합니다. 예를 들어 java.lang 패키지 클래스입니다.

확장 클래스 로더: 클래스 로딩 요청을 상위 항목에 위임합니다. 클래스 로딩에 실패하면 jre/lib/ext 디렉터리 또는 다른 디렉터리에서 java.ext.dirs로 클래스를 로드합니다. JVM의 sun.misc.Launcher$ExtClassLoader에 의해 구현됩니다.

시스템 클래스 로더: CLASSPATH 환경 변수에서 애플리케이션별 클래스를 로드합니다. -cp 또는 classpath 명령줄 옵션을 사용하여 프로그램을 호출하는 동안 설정할 수 있습니다. Extension ClassLoader의 하위 항목입니다. sun.misc.Launcher$AppClassLoader 클래스에 의해 구현됩니다. 모든 Java ClassLoader는 java.lang.ClassLoader를 구현합니다.

Java의 클래스로더

ClassLoader가 Java에서 작동하는 방식

JVM이 클래스를 요청할 때 클래스의 완전히 분류된 이름을 전달하여 java.lang.ClassLoader 클래스의 loadClass() 메서드를 호출합니다. loadClass() 메서드는 클래스가 이미 로드되었는지 여부를 확인하기 위해 findLoadedClass() 메서드를 호출합니다. 클래스를 여러 번 로드하지 않도록 해야 합니다.

클래스가 이미 로드된 경우 해당 클래스를 로드하도록 요청을 상위 ClassLoader에 위임합니다. ClassLoader가 클래스를 찾지 못하면 findClass() 메서드를 호출하여 파일 시스템에서 클래스를 찾습니다. 다음 다이어그램은 ClassLoader가 위임을 사용하여 Java에서 클래스를 로드하는 방법을 보여줍니다.

Java의 클래스로더

애플리케이션 특정 클래스 Demo.class가 있다고 가정합니다. 이 클래스 파일 로드 요청은 Application ClassLoader로 전송됩니다. 상위 Extension ClassLoader에 위임합니다. 또한 Bootstrap ClassLoader에 위임합니다. 부트스트랩은 rt.jar에서 해당 클래스를 검색합니다. 해당 클래스가 없기 때문입니다. 이제 jre/lib/ext 디렉토리를 검색하고 거기에서 이 클래스를 찾으려고 시도하는 Extension ClassLoader로 전송을 요청합니다. 클래스가 거기에서 발견되면 Extension ClassLoader는 해당 클래스를 로드합니다. 애플리케이션 ClassLoader는 해당 클래스를 로드하지 않습니다. 확장 ClassLoader가 이를 로드하지 않으면 Application ClaasLoader는 Java의 CLASSPATH에서 이를 로드합니다.

가시성 원칙에 따르면 하위 ClassLoader는 상위 ClassLoader가 로드한 클래스를 볼 수 있지만 그 반대의 경우는 그렇지 않습니다. 이는 애플리케이션 ClassLoader가 Demo.class를 로드하는 경우, 확장 ClassLoader를 사용하여 명시적으로 Demo.class를 로드하려고 시도하면 java.lang.ClassNotFoundException이 발생함을 의미합니다.

고유성 원칙에 따라 상위 클래스가 로드한 클래스는 하위 ClassLoader에 의해 다시 로드되어서는 안 됩니다. 따라서 위임 및 고유성 원칙을 위반하고 클래스 자체를 로드하는 클래스 로더를 작성하는 것이 가능합니다.

즉, 클래스 로더는 다음 규칙을 따릅니다.

  • 클래스가 이미 로드되었는지 확인합니다.
  • 클래스가 로드되지 않은 경우 상위 클래스 로더에 클래스 로드를 요청하세요.
  • 상위 클래스 로더가 클래스를 로드할 수 없는 경우 이 클래스 로더에서 로드를 시도하십시오.

다음 예를 고려하십시오.

 public class Demo { public static void main(String args[]) { System.out.println('How are you?'); } } 

다음 명령을 사용하여 위 코드를 컴파일하고 실행합니다.

 javac Demo.java java -verbose:class Demo 

-상세:클래스: JVM이 로드하는 클래스에 대한 정보를 표시하는 데 사용됩니다. 클래스를 동적으로 로드하기 위해 클래스 로더를 사용할 때 유용합니다. 다음 그림은 출력을 보여줍니다.

Java의 클래스로더

애플리케이션 클래스(Demo)에 필요한 런타임 클래스가 먼저 로드되는 것을 볼 수 있습니다.

클래스가 로드될 때

두 가지 경우만 있습니다:

  • 새로운 바이트 코드가 실행될 때.
  • 바이트 코드가 클래스에 대한 정적 참조를 만드는 경우. 예를 들어, 시스템아웃 .

정적 클래스 로딩과 동적 클래스 로딩

클래스는 'new' 연산자를 사용하여 정적으로 로드됩니다. 동적 클래스 로딩은 Class.forName() 메소드를 사용하여 런타임 시 클래스 로더의 기능을 호출합니다.

loadClass()와 Class.forName()의 차이점

loadClass() 메서드는 클래스만 로드하고 객체를 초기화하지는 않습니다. Class.forName() 메소드는 객체를 로드한 후 객체를 초기화합니다. 예를 들어 ClassLoader.loadClass()를 사용하여 JDBC 드라이버를 로드하는 경우 클래스 로더는 JDBC 드라이버 로드를 허용하지 않습니다.

java.lang.Class.forName() 메소드는 주어진 문자열 이름을 가진 클래스 또는 인터페이스와 결합된 클래스 객체를 반환합니다. 클래스를 찾을 수 없으면 ClassNotFoundException이 발생합니다.

이 예에서는 java.lang.String 클래스가 로드됩니다. 클래스 이름, 패키지 이름 및 String 클래스의 사용 가능한 모든 메소드 이름을 인쇄합니다. 다음 예제에서는 Class.forName()을 사용하고 있습니다.

수업: 모든 유형이 가능한 Class 객체를 나타냅니다(?는 와일드카드입니다). Class 유형에는 클래스에 대한 메타 정보가 포함되어 있습니다. 예를 들어 String.class의 유형은 Class입니다. 모델링되는 클래스를 알 수 없는 경우 클래스를 사용하십시오.

getDeclared메소드(): 공용, 보호, 기본(패키지) 액세스 및 전용 메서드를 포함하여 이 Class 개체가 나타내는 클래스 또는 인터페이스의 모든 선언된 메서드를 반영하지만 상속된 메서드는 제외하는 Method 개체가 포함된 배열을 반환합니다.

getName(): 이 Method 객체가 나타내는 메소드 이름을 문자열로 반환합니다.

 import java.lang.reflect.Method; public class ClassForNameExample { public static void main(String[] args) { try { Class cls = Class.forName('java.lang.String'); System.out.println('Class Name: ' + cls.getName()); System.out.println('Package Name: ' + cls.getPackage()); Method[] methods = cls.getDeclaredMethods(); System.out.println('-----Methods of String class -------------'); for (Method method : methods) { System.out.println(method.getName()); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } 

산출

 Class Name: java.lang.String Package Name: package java.lang -----Methods of String class ------------- value coder equals length toString hashCode getChars ------ ------ ------ intern isLatin1 checkOffset checkBoundsOffCount checkBoundsBeginEnd access0 access0