JVM 동적 클래스 로딩
클래스 로더란 '.class' 바이트 코드를 읽어 들여 class 객체를 생성하는 역할을 담당한다. 즉, 클래스 로더는 클래스가 요청될 때 파일로부터 읽어 메모리로 로딩하는 역할을 하며 자바 가상 머신의 중요한 요소 중 하나다.
※ 클래스 로더가 classpath라는 환경 변수에 등록된 디렉토리에 있는 모든 클래스들을 먼저 JVM에 로딩한다. JVM에 로딩된 클래스만이 JVM에서 객체로 사용할 수 있다. 클래스 로딩은 클래스를 로딩하는 시점 또는 실행 중간에도 할 수 있다.
자바의 클래스 로딩은 세부적으로 로딩, 링크, 초기화라는 세 단계 과정을 거친다.
- 로딩 : 클래스 파일을 바이트 코드로 읽어 메모리로 가져오는 과정
- 링크 : 가장 복잡한 과정으로, 읽어본 바이트 코드가 자바 규칙을 따르는지 검증하고, 클래스에 정의된 필드, 메소드, 인터페이스들을 나타내는 데이터 구조를 준비하며, 그 클래스가 참조하는 다른 클래스를 로딩한다.
- 초기화 : 슈퍼 클래스 및 정적 필드를 초기화한다.
동적 Java 클래스 로딩은 주로 Java Reflection. Java Reflection JVM에서 실행되는 애플리케이션의 런타임 동작을 검사하거나 수정할 수 있는 기능을 제공합니다. 또한 런타임에 특정 클래스에서 사용될 메서드와 속성을 결정하는 데 사용됩니다.
따라서 프로그램을 변경할 필요없이 프로그램에 추가 기능을 추가할 수 있는 프로그래머와 사용자 모두에게 유연성을 제공하는 플러그인 아키텍처를 대상으로 하는 경우. Java 동적 Java 클래스 로딩 Java Reflection 은이 접근 방식을 달성하기 위한 메커니즘입니다.
로드타임 동적 로딩(load-time dynamic loading)과 런타임 동적 로딩(run-time dynamic loading)
로드타임 동적 로딩(load-time dynamic loading)
public class HelloWorld {
public static void main(String[] args) {
System.out.println("안녕하세요!");
}
}
HelloWorld 클래스를 실행하였다고 가정
부트스트랩 클래스로더가 생성된 후에, 모든 클래스가 상속받고 있는 Object 클래스를 읽어온다. 그 이후에, 클래스로더는 명령행에서 지정한 HelloWorld 클래스를 로딩하기 위해, HelloWorld.class 파일을 읽는다. HelloWorld 클래스를 로딩하는 과정에서 필요한 클래스가 존재한다. 바로 java.lang.String과 java.lang.System이다. 이 두 클래스는 HelloWorld 클래스를 읽어오는 과정에서, 즉 로드타임에 로딩된다. 이 처럼, 하나의 클래스를 로딩하는 과정에서 동적으로 클래스를 로딩하는 것을 로드타임 동적 로딩이라고 한다.
Object 클래스를 읽어온다 → HelloWorld클래스를 로딩하기 위해 HelloWorld.class 파일을 읽는다 → 로딩과정에서 java.lang.String, System이 필요하다 → 클래스를 읽어오는 과정에서 로드타임에 로딩
런타임 동적 로딩(run-time dynamic loading)
public class HelloWorld1 implements Runnable {
public void run() {
System.out.println("안녕하세요, 1");
}
}
public class HelloWorld2 implements Runnable {
public void run() {
System.out.println("안녕하세요, 2");
}
}
public class RuntimeLoading {
public static void main(String[] args) {
try {
if (args.length < 1) {
System.out.println("사용법: java RuntimeLoading [클래스 이름]");
System.exit(1);
}
Class klass = Class.forName(args[0]);
Object obj = klass.newInstance();
Runnable r = (Runnable) obj;
r.run();
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
위 코드에서, Class.forName(className)은 파리미터로 받은 className에 해당하는 클래스를 로딩한 후에, 그 클래스에 해당하는 Class 인스턴스(로딩한 클래스의 인스턴스가 아니다!)를 리턴한다. Class 클래스의 newInstance() 메소드는 Class가 나타내는 클래스의 인스턴스를 생성한다. 예를 들어, 다음과 같이 한다면 java.lang.String 클래스의 객체가 생성된다.
Class klass = Class.forName("java.lang.String");
Object obj = klass.newInstance();
따라서, Class.forName() 메소드가 실행되기 전까지는 RuntimeLoading 클래스에서 어떤 클래스를 참조하는 지 알수 없다. 다시 말해서, RuntimeLoading 클래스를 로딩할 때는 어떤 클래스도 읽어오지 않고, RuntimeLoading 클래스의 main() 메소드가 실행되고 Class.forName(args[0])를 호출하는 순간에 비로서 args[0]에 해당하는 클래스를 읽어온다. 이처럼 클래스를 로딩할 때가 아닌 코드를 실행하는 순간에 클래스를 로딩하는 것을 런타임 동적 로딩이라고 한다.
.java 파일로 작성되었던 소스코드가 어떻게 JVM위로 로딩되는지 과정
.java 파일 → bytecode 변환후 로딩 → 메모리에 저장 → 로딩 → 링크 → 초기화
결론
로드타임 동적 로딩은(load-time dynamic loading)의 약자이고
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!!!");
}
}
라는 HelloWorld 클래스를 실행하였다고 가정하고 말해보겠습니다.
부트스트랩 클래스로더가 생성된 후에 모든 클래스가 상속 받고 있는 Object클래스를 읽어오고 그 후에 클래스로더는 명령행에서 지정한 HelloWorld 클래스를 로딩하기 위해서, 컴파일된 HelloWorld.class
파일을 읽습니다. HelloWorld 클래스를 로딩하는 과정에서 필요한 클래스가 존재하는데 현재 예시에서는 java.lang.String
과 java.lang.System
클래스입니다. 이 두 클래스는 HelloWorld 클래스를 읽어오는 과정에서 로드타임에 로딩이 됩니다.
이렇게 하나의 클래스를 로딩하는 과정에서 동적으로 클래스를 로딩하는 것을 로드타임 동적로딩이라고합니다.
간략하게 순서를 나열해보면 Object Class를 읽는다 ->HelloWorld 클래스를 Loading 하기 위해서 HelloWorld.class
파일을 읽는다 -> 로딩 과정에서 java.lang.String
, System 클래스를 읽는다 -> 클래스를 읽어오는 과정에서 로드타임에 로딩한다
런타임 동적 로딩은(Run-time dynamic loading)의 약자입니다.
public class HelloWorld {
public static void main(String[] args) {
Class c = Class.forName(args[0]);
}
}
라는 HelloWorld 클래스를 실행하였다고 가정하고 말해보겠습니다.
객체를 참조하는 순간에 동적으로 Loading 하는 방식입니다. 위 코드에서, Class.forName(args[0])
은 파리미터로 받은 (args[0])
에 해당하는 클래스를 로딩한 후에, 그 클래스에 해당하는 Class 인스턴스를 리턴하게 됩니다. Class.forName()
메소드가 실행되기 전까지는 HelloWorld 클래스에서 어떤 클래스를 참조하는지는 알수 없고 이것을 알려면 인자로 넘어오는 args[0]
가 인수로 넘어온 후에나 알 수 있습니다. 이처럼 클래스를 로딩할 떄가 아닌 코드를 실행하는 순간에 클래스를 로딩하는 것을 런타임 동적 로딩이라고 합니다.
Reference
'Java > 개념' 카테고리의 다른 글
Java 8 LocalDateTime vs Instant 어떤 상황에서 쓰는게 적합한가? (0) | 2022.08.09 |
---|---|
Java 메모리 최적화가 어떻게 되는지 과정 (0) | 2021.02.25 |
[Java] Java 8에 추가된 LocalDate, LocalTime, LocalDateTime (0) | 2020.11.02 |
[Java] Date, Calendar클래스가 왜 Deprecated됐는지? (0) | 2020.11.02 |
[Java] Date와 Calendar 클래스 (0) | 2020.11.02 |