클래스 로더(Class Loader)
클래스 로더(Class Loader)는 자바 가상 머신(JVM)의 중요한 구성 요소로, 클래스 파일(.class)을 메모리로 로드하여 실행할 수 있게 하는 역할을 담당합니다. 클래스 로더는 자바의 동적 로딩(dynamic loading)을 가능하게 하며, 프로그램이 실행되는 동안 필요한 클래스를 동적으로 메모리에 적재합니다.
클래스 로더의 역할
- 클래스 파일 로딩:
- 클래스 로더는 .class 파일을 파일 시스템, JAR 파일, 네트워크 등의 다양한 소스에서 읽어들이고, 이를 JVM의 메모리로 로드합니다.
- 자바 프로그램이 실행될 때, 클래스 로더는 필요한 클래스를 동적으로 로드하여 JVM에서 사용할 수 있게 만듭니다.
- 클래스 파일 검증:
- 클래스 로더는 로드된 클래스 파일의 바이트코드를 검증합니다. 이 검증 과정은 클래스 파일이 자바 언어 명세에 맞게 작성되었는지, 그리고 보안적으로 안전한지 확인합니다.
- 이 과정에서 문제가 발생하면 JVM은 예외를 던지며 프로그램이 실행되지 않습니다.
- 클래스 네임스페이스 관리:
- 클래스 로더는 클래스 이름과 해당 클래스가 속한 패키지를 조합하여 고유한 네임스페이스를 관리합니다. 이를 통해 동일한 이름의 클래스를 서로 다른 네임스페이스에서 독립적으로 로드할 수 있습니다.
- 예를 들어, 두 개의 서로 다른 JAR 파일에 동일한 이름을 가진 클래스가 있다면, 각각의 클래스 로더에 의해 별도로 관리됩니다.
- 클래스 로딩 순서 관리:
- 클래스 로더는 자바의 부모 위임 모델을 사용하여 클래스를 로드합니다. 이 모델에 따르면, 클래스 로더는 먼저 부모 클래스 로더에게 클래스를 로드하도록 요청하며, 부모 클래스 로더가 해당 클래스를 로드할 수 없는 경우에만 자식 클래스 로더가 클래스를 로드합니다.
- 이를 통해 클래스 로딩 과정에서의 충돌을 방지하고, 클래스 로딩의 일관성을 유지합니다.
- 동적 클래스 로딩:
- 자바는 실행 중에도 새로운 클래스를 동적으로 로드할 수 있습니다. 이 기능은 플러그인 시스템이나 모듈 시스템에서 중요한 역할을 합니다.
- ClassLoader 클래스를 사용하여 사용자 정의 클래스 로더를 구현하면, 네트워크나 데이터베이스 등에서 클래스를 동적으로 로드할 수 있습니다.
클래스 로더의 종류
자바에는 여러 종류의 클래스 로더가 있으며, 이들은 계층적으로 구성되어 있습니다:
- 부트스트랩 클래스 로더 (Bootstrap Class Loader):
- JVM의 가장 기본이 되는 클래스 로더로, 자바 표준 라이브러리(예: java.lang, java.util 패키지의 클래스)를 로드합니다.
- 자바 네이티브 코드(C++)로 구현되어 있으며, 자바 코드에서 직접 접근할 수 없습니다.
- 확장 클래스 로더 (Extension Class Loader):
- JRE의 lib/ext 디렉토리에 있는 클래스들을 로드합니다.
- 표준 라이브러리 외의 추가적인 확장 라이브러리를 로드할 때 사용됩니다.
- 애플리케이션 클래스 로더 (Application Class Loader):
- 애플리케이션이 사용하는 클래스들을 로드합니다. 이는 classpath에 지정된 디렉토리와 JAR 파일에서 클래스를 로드합니다.
- 일반적인 자바 애플리케이션에서 개발자가 작성한 클래스와 외부 라이브러리를 로드하는 역할을 합니다.
사용자 정의 클래스 로더
- 자바에서는 ClassLoader 클래스를 상속하여 사용자 정의 클래스 로더를 만들 수 있습니다. 이 기능을 통해 특정 요구사항에 맞는 클래스 로딩 동작을 구현할 수 있습니다.
- 예를 들어, 플러그인 시스템에서는 사용자 정의 클래스 로더를 사용하여 네트워크나 특정 경로에서 클래스를 로드할 수 있습니다.
method.invoke
.invoke 메서드는 주로 자바 리플렉션(Reflection) API의 Method 클래스에 존재하며, 메서드를 동적으로 호출할 때 사용됩니다. 따라서, .invoke는 자바에서 특정 메서드와 관련된 동작을 수행할 때만 사용되는 것이 맞습니다.
.invoke 메서드의 주요 특징
- 자바 리플렉션에서 사용:
- .invoke는 java.lang.reflect.Method 클래스의 메서드로, 런타임에 동적으로 메서드를 호출하는 데 사용됩니다.
- 예를 들어, 특정 객체에서 특정 메서드를 동적으로 호출할 때 Method 객체의 invoke 메서드를 사용합니다.
- 메서드 호출:
- .invoke 메서드는 두 가지 인자를 받습니다:
- 첫 번째 인자: 메서드를 호출할 객체입니다. 이 객체가 메서드가 속한 인스턴스입니다. 만약 호출하는 메서드가static메서드라면, 이 인자에null을 전달할 수 있습니다.
- 두 번째 인자: 메서드 호출에 필요한 인자들을 포함한 Object[] 배열입니다. 인자가 없을 경우 빈 배열 또는 null을 전달할 수 있습니다.
- .invoke 메서드는 두 가지 인자를 받습니다:
.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 클래스와 인터페이스의 특징
- 클래스의 확장 제한:
- sealed 키워드를 사용하면 해당 클래스를 상속할 수 있는 클래스나 인터페이스를 명시적으로 지정할 수 있습니다.
- 이로 인해 클래스 계층 구조의 확장 가능성을 제한하여, 의도하지 않은 상속으로 인한 문제를 방지할 수 있습니다.
- 허용된 클래스 명시:
- sealed 클래스를 확장할 수 있는 클래스들은 permits 키워드를 사용하여 명시합니다. 오직 permits로 명시된 클래스들만 해당 클래스를 상속할 수 있습니다.
- 확장 가능한 클래스의 종류:
- sealed 클래스는 다음 세 가지 방식으로 확장될 수 있습니다:
- final: 해당 클래스를 더 이상 상속할 수 없습니다.
- non-sealed: 해당 클래스를 상속할 수 있으며, 이는 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(정규화된 이름)은 자바에서 클래스, 인터페이스, 메서드, 필드 등을 고유하게 식별하기 위해 전체 경로를 포함한 이름을 의미합니다. 주로 패키지와 클래스 이름을 함께 사용하는 경우를 말하며, 클래스 이름이 중복될 수 있는 경우에 특히 중요합니다.
주요 사용 예
- 클래스의 Qualified Name:
- 클래스의 패키지 경로와 클래스 이름을 함께 사용하여 고유하게 식별합니다.
- 예: java.util.ArrayList
- 여기서 java.util은 패키지 이름이고, ArrayList는 클래스 이름입니다.
- 내부 클래스의 Qualified Name:
- 내부 클래스의 경우, 외부 클래스의 이름과 내부 클래스의 이름을 함께 사용하여 고유하게 식별합니다.
- 예: OuterClass.InnerClass
- 여기서 OuterClass는 외부 클래스 이름이고, InnerClass는 내부 클래스 이름입니다.
- 메서드의 Qualified Name:
- 메서드 이름 앞에 클래스 이름을 붙여서 메서드를 고유하게 식별할 수 있습니다.
- 예: java.util.List.add
- 여기서 add는 메서드 이름이고, List는 이 메서드가 속한 인터페이스 또는 클래스 이름입니다.
- 필드의 Qualified Name:
- 클래스 이름과 필드 이름을 함께 사용하여 필드를 고유하게 식별할 수 있습니다.
- 예: java.lang.Integer.MAX_VALUE
- 여기서 MAX_VALUE는 Integer 클래스의 상수 필드입니다.
'Study Memo' 카테고리의 다른 글
2024.08.22(목) { Qualified Name, @DirtiesContext, 체이닝 메서드, MOCK } (0) | 2024.08.22 |
---|---|
2024.08.21(수) { enum 클래스의 자동생성되는 것, InvocationHandler } (0) | 2024.08.21 |
2024.08.19(월) { 타겟 클래스, Stream } (0) | 2024.08.20 |
2024.08.16(금) { 와일드카드 캡쳐, transient } (0) | 2024.08.16 |
2024.08.15(목) { ( @component,@Bean,@Autowired ), 커밋, Thread Context } (0) | 2024.08.15 |