본문 바로가기
Everyday Study

2024.08.20(화) { 클래스 로더, .invoke, seald, qualified name }

by xogns93 2024. 8. 20.

클래스 로더(Class Loader)

 

클래스 로더(Class Loader)는 자바 가상 머신(JVM)의 중요한 구성 요소로, 클래스 파일(.class)을 메모리로 로드하여 실행할 수 있게 하는 역할을 담당합니다. 클래스 로더는 자바의 동적 로딩(dynamic loading)을 가능하게 하며, 프로그램이 실행되는 동안 필요한 클래스를 동적으로 메모리에 적재합니다.

클래스 로더의 역할

  1. 클래스 파일 로딩:
    • 클래스 로더는 .class 파일을 파일 시스템, JAR 파일, 네트워크 등의 다양한 소스에서 읽어들이고, 이를 JVM의 메모리로 로드합니다.
    • 자바 프로그램이 실행될 때, 클래스 로더는 필요한 클래스를 동적으로 로드하여 JVM에서 사용할 수 있게 만듭니다.
  2. 클래스 파일 검증:
    • 클래스 로더는 로드된 클래스 파일의 바이트코드를 검증합니다. 이 검증 과정은 클래스 파일이 자바 언어 명세에 맞게 작성되었는지, 그리고 보안적으로 안전한지 확인합니다.
    • 이 과정에서 문제가 발생하면 JVM은 예외를 던지며 프로그램이 실행되지 않습니다.
  3. 클래스 네임스페이스 관리:
    • 클래스 로더는 클래스 이름과 해당 클래스가 속한 패키지를 조합하여 고유한 네임스페이스를 관리합니다. 이를 통해 동일한 이름의 클래스를 서로 다른 네임스페이스에서 독립적으로 로드할 수 있습니다.
    • 예를 들어, 두 개의 서로 다른 JAR 파일에 동일한 이름을 가진 클래스가 있다면, 각각의 클래스 로더에 의해 별도로 관리됩니다.
  4. 클래스 로딩 순서 관리:
    • 클래스 로더는 자바의 부모 위임 모델을 사용하여 클래스를 로드합니다. 이 모델에 따르면, 클래스 로더는 먼저 부모 클래스 로더에게 클래스를 로드하도록 요청하며, 부모 클래스 로더가 해당 클래스를 로드할 수 없는 경우에만 자식 클래스 로더가 클래스를 로드합니다.
    • 이를 통해 클래스 로딩 과정에서의 충돌을 방지하고, 클래스 로딩의 일관성을 유지합니다.
  5. 동적 클래스 로딩:
    • 자바는 실행 중에도 새로운 클래스를 동적으로 로드할 수 있습니다. 이 기능은 플러그인 시스템이나 모듈 시스템에서 중요한 역할을 합니다.
    • ClassLoader 클래스를 사용하여 사용자 정의 클래스 로더를 구현하면, 네트워크나 데이터베이스 등에서 클래스를 동적으로 로드할 수 있습니다.

 

클래스 로더의 종류

자바에는 여러 종류의 클래스 로더가 있으며, 이들은 계층적으로 구성되어 있습니다:

  1. 부트스트랩 클래스 로더 (Bootstrap Class Loader):
    • JVM의 가장 기본이 되는 클래스 로더로, 자바 표준 라이브러리(예: java.lang, java.util 패키지의 클래스)를 로드합니다.
    • 자바 네이티브 코드(C++)로 구현되어 있으며, 자바 코드에서 직접 접근할 수 없습니다.
  2. 확장 클래스 로더 (Extension Class Loader):
    • JRE의 lib/ext 디렉토리에 있는 클래스들을 로드합니다.
    • 표준 라이브러리 외의 추가적인 확장 라이브러리를 로드할 때 사용됩니다.
  3. 애플리케이션 클래스 로더 (Application Class Loader):
    • 애플리케이션이 사용하는 클래스들을 로드합니다. 이는 classpath에 지정된 디렉토리와 JAR 파일에서 클래스를 로드합니다.
    • 일반적인 자바 애플리케이션에서 개발자가 작성한 클래스와 외부 라이브러리를 로드하는 역할을 합니다.

사용자 정의 클래스 로더

  • 자바에서는 ClassLoader 클래스를 상속하여 사용자 정의 클래스 로더를 만들 수 있습니다. 이 기능을 통해 특정 요구사항에 맞는 클래스 로딩 동작을 구현할 수 있습니다.
  • 예를 들어, 플러그인 시스템에서는 사용자 정의 클래스 로더를 사용하여 네트워크나 특정 경로에서 클래스를 로드할 수 있습니다.

 


method.invoke

 

.invoke 메서드는 주로 자바 리플렉션(Reflection) API의 Method 클래스에 존재하며, 메서드를 동적으로 호출할 때 사용됩니다. 따라서, .invoke는 자바에서 특정 메서드와 관련된 동작을 수행할 때만 사용되는 것이 맞습니다.

.invoke 메서드의 주요 특징

  1. 자바 리플렉션에서 사용:
    • .invoke는 java.lang.reflect.Method 클래스의 메서드로, 런타임에 동적으로 메서드를 호출하는 데 사용됩니다.
    • 예를 들어, 특정 객체에서 특정 메서드를 동적으로 호출할 때 Method 객체의 invoke 메서드를 사용합니다.
  2. 메서드 호출:
    • .invoke 메서드는 두 가지 인자를 받습니다:
      • 첫 번째 인자: 메서드를 호출할 객체입니다. 이 객체가 메서드가 속한 인스턴스입니다. 만약 호출하는 메서드가static메서드라면, 이 인자에null을 전달할 수 있습니다.
      • 두 번째 인자: 메서드 호출에 필요한 인자들을 포함한 Object[] 배열입니다. 인자가 없을 경우 빈 배열 또는 null을 전달할 수 있습니다.

.invoke 사용 예제

import java.lang.reflect.Method;

public class ReflectionExample {
    public static void main(String[] args) throws Exception {
        // 예시 클래스
        class Example {
            public void sayHello(String name) {
                System.out.println("Hello, " + name);
            }
        }

        // Example 클래스의 인스턴스 생성
        Example example = new Example();

        // Method 객체를 통해 sayHello 메서드를 얻음
        Method method = Example.class.getMethod("sayHello", String.class);

        // invoke를 사용하여 sayHello 메서드 호출
        method.invoke(example, "World");
    }
}
Hello, World

 


sealed 키워드

 

sealed는 Java 15에서 도입된 기능으로, 클래스 계층 구조를 더욱 엄격하게 제어할 수 있도록 해줍니다. sealed 키워드를 사용하면 특정 클래스 또는 인터페이스가 어떤 클래스나 인터페이스에 의해 확장(상속)될 수 있는지를 명시적으로 제한할 수 있습니다. 이를 통해 클래스 계층 구조의 확장을 더 안전하고, 예상 가능한 방식으로 관리할 수 있습니다.

 

sealed 클래스와 인터페이스의 특징

  1. 클래스의 확장 제한:
    • sealed 키워드를 사용하면 해당 클래스를 상속할 수 있는 클래스나 인터페이스를 명시적으로 지정할 수 있습니다.
    • 이로 인해 클래스 계층 구조의 확장 가능성을 제한하여, 의도하지 않은 상속으로 인한 문제를 방지할 수 있습니다.
  2. 허용된 클래스 명시:
    • sealed 클래스를 확장할 수 있는 클래스들은 permits 키워드를 사용하여 명시합니다. 오직 permits로 명시된 클래스들만 해당 클래스를 상속할 수 있습니다.
  3. 확장 가능한 클래스의 종류:
    • sealed 클래스는 다음 세 가지 방식으로 확장될 수 있습니다:
      • final: 해당 클래스를 더 이상 상속할 수 없습니다.
      • non-sealed: 해당 클래스를 상속할 수 있으며, 이는 sealed 클래스와 동일한 효과를 가집니다.
      • sealed: 해당 클래스도 역시 제한된 클래스로 확장될 수 있습니다.
// 상위 클래스 정의
public sealed class Shape permits Circle, Rectangle {
    // 공통 로직 또는 필드 정의
}

// 하위 클래스들 정의
public final class Circle extends Shape {
    // Circle에 대한 구현
}

public non-sealed class Rectangle extends Shape {
    // Rectangle에 대한 구현
}

public sealed class Triangle extends Shape permits EquilateralTriangle {
    // Triangle에 대한 구현
}

// Triangle 클래스를 확장하는 클래스
public final class EquilateralTriangle extends Triangle {
    // EquilateralTriangle에 대한 구현
}

예제 설명

  • Shape 클래스: sealed 클래스로 정의되어 있으며, 이 클래스를 상속할 수 있는 클래스는 Circle, Rectangle, Triangle로 제한되어 있습니다.
  • Circle 클래스: final 클래스로 정의되어 있으며, 이를 통해 더 이상 상속할 수 없습니다.
  • Rectangle 클래스: non-sealed 클래스로 정의되어 있으며, Rectangle은 상속이 가능하며, 일반 클래스처럼 동작합니다.
  • Triangle 클래스: sealed 클래스로 정의되어 있으며, EquilateralTriangle 클래스만이 이를 확장할 수 있습니다.
  • EquilateralTriangle 클래스: final 클래스로 정의되어 있으며, 더 이상 상속할 수 없습니다.

qualified name

 

Qualified Name(정규화된 이름)은 자바에서 클래스, 인터페이스, 메서드, 필드 등을 고유하게 식별하기 위해 전체 경로를 포함한 이름을 의미합니다. 주로 패키지와 클래스 이름을 함께 사용하는 경우를 말하며, 클래스 이름이 중복될 수 있는 경우에 특히 중요합니다.

주요 사용 예

  1. 클래스의 Qualified Name:
    • 클래스의 패키지 경로와 클래스 이름을 함께 사용하여 고유하게 식별합니다.
    • 예: java.util.ArrayList
      • 여기서 java.util은 패키지 이름이고, ArrayList는 클래스 이름입니다.
  2. 내부 클래스의 Qualified Name:
    • 내부 클래스의 경우, 외부 클래스의 이름과 내부 클래스의 이름을 함께 사용하여 고유하게 식별합니다.
    • 예: OuterClass.InnerClass
      • 여기서 OuterClass는 외부 클래스 이름이고, InnerClass는 내부 클래스 이름입니다.
  3. 메서드의 Qualified Name:
    • 메서드 이름 앞에 클래스 이름을 붙여서 메서드를 고유하게 식별할 수 있습니다.
    • 예: java.util.List.add
      • 여기서 add는 메서드 이름이고, List는 이 메서드가 속한 인터페이스 또는 클래스 이름입니다.
  4. 필드의 Qualified Name:
    • 클래스 이름과 필드 이름을 함께 사용하여 필드를 고유하게 식별할 수 있습니다.
    • 예: java.lang.Integer.MAX_VALUE
      • 여기서 MAX_VALUE는 Integer 클래스의 상수 필드입니다.