* Intro
- Java는 컴파일 시점이 아닌 런타임 시점에 클래스를 로드하고 링크 하는 동적 로딩 방식을 사용한다.
이때 각 클래스를 동적으로 로드하는 역할을 Class Loader( 클래스 로더 )가 담당한다.
- 동적 로딩은 loading - link - init (로딩 - 링크 - 초기화) 과정을 거쳐 명령을 실행한다.
* 로딩
- 바이트코드를 메서드 영역에 적재한다.
- JVM은 메서드 영역에 읽어온 바이트 코드들의 정보를 저장한다. ( 아래와 같다 )
a) 로드된 클래스와 그 부모 클래스 정보.
b) 클래스 파일과 Class, Interface, Enum 관련 여부.
c) 변수나 메서드 정보.
* 링크
a) 검증
- 읽어온 클래스가 자바 및 JVM 명세에 명시된 대로 잘 구성됐는지 검사한다.
b) 준비
- 클래스가 필요로 하는 메모리를 할당하고 정의된 클래스, 인퍼페이스, 필드 메서드를 나타내는 데이터 구조를 준비한다.
c) 분석
- 심볼릭 메모리 레퍼러스 메서드 영역 내 실제 레퍼런스로 바꾼다.
* 초기화
- 클래스 변수들을 적절한 값으로 초기화 한다. -> 정적 필드를 설정된 값으로 초기화 한다.
1. 종류
* 1.1 부트스트랩 클래스 로더 Bootstrap Class Loader
- 클래스 로더 계층 구조 상 최상위 계층 클래스 로더.
자바 클래스를 로드 할 수 있는 자바 자체의 클래스 로더와 Object 클래스를 로드한다.
* ~ Java 8 : /jre/lib/rt/jar 와 기타 핵심 라이브러리 등 JDK 내부 클래스를 로드한다.
* Java 9 ~ : /rt.jar 가 /lib 내에 모듈화 되어 포함되어 자바 자체의 클래스 로더만 로드한다.
* 1.2 확장 클래스 로더 Extension Class Loader -> Java 9 부터 Platform Class Loader 로 변경
- 부트스트랩 클래스 로더의 자식 클래스 로더로 확장 자바 클래스를 로드한다.
* 1.3 시스템 클래스 로더 System Class Loader
- 사용자가 지정한 ${CLASSPATH}의 클래스를 로드한다.
* 1.4 사용자 정의 클래스 로더 User - Defined Class Loader
- 클래스 로더 중 최하위 계층으로, 애플리케이션 레벨에서 사용자가 직접 정의하고 생성한 클래스 로더.
2. 동작 방식
- 새로운 클래스를 로드할 경우 다음과 같은 절차를 따른다.
a) 메서드 영역에 클래스가 적재돼있는지 확인한다.
b) 메서드 영역에서 찾을 수 없을 경우 시스템 클래스 로더에 요청하고 시스템 클래스 로더는 확장 클래스 로더에 요청을 넘긴다.
c) 확장 클래스 로더는 부트스트랩 클래스 로더에 요청을 넘기고 부트스트랩 클래스 로더는 부트스트랩 경로에 해당 클래스가 존재하는지 확인한다.
d) 클래스가 없다면 다시 확장 클래스 로더로 요청을 넘기고 확장 클래스 로더는 확장 경로에서 찾아본다.
e) 확장 클래스 로더에서도 찾을 수 없다면 시스템 클래스 로더에서 시스템 경로에서 찾는다. 이 때 찾을 수 없다면 ClassNotFoundException 을 발생시킨다.
3. 클래스 로더 3 원칙
3.1 위임 원칙
- 클래스 로더는 리소스를 찾을 때 상위 클래스 로더로 요청을 위임한다.
3.2 가시 범위 원칙
- 하위 클래스 로더는 상위 클래스 로더가 로드한 클래스를 알 수 있지만 상위 클래스 로더는 하위 클래스 로더가 로드한 클래스를 알 수 없다.
3.3 유일성 원칙
- 하위 클래스 로더는 상위 클래스 로더가 로드한 클래스를 다시 로드하면 안된다.
- 위임 원칙으로 고유한 클래스 로딩을 보장 할 수 있다.
4. 동적 로딩
4.1 로드타임 동적 로딩
public class HelloWorld {
public static void main(String[] args) {
System.out.println("hello world!!");
}
}
- 위처럼 hello world!!! 를 출력 하는 코드를 컴파일 과정 이후 실행 했을때 클래스 로더는 Object 클래스와 HelloWorld 클래스를 읽고 로딩하기 위해 필요한 String, System 클래스를 로딩한다.
- 여기서 모든 클래스는 HelloWorld 클래스가 실행 되기 전 로드타임에 동적으로 로드 된다.
4.2 런타임 동적 로딩
- 객체지향 다형성 원리를 이용해 런타임 동적 로딩을 알아보자.
- 다음과 같이 Main, Car, SportsCar 클래스 코드를 이용하여 세개의 파일을 만들고 실행하자.
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
Car car = new SportsCar();
car.move();
}
}
---
public interface Car {
void move();
}
---
public class SportsCar implements Car {
@Override
public void move() {
System.out.println("Sports car move!!!");
}
}
결과 화면
Hello world!
Sports car move!!!
이 떄 클래스 로딩 로그를 확인해보려면 터미널을 열고 다음 명령어를 입력해보면 된다.
java classpath ${바이트코드 경로} -verbose:class ${메인클래스 명}
// ex) java classpath ./out/production/hello-world verbose:class Main
로그를 출력해보면 다음과 같이 어마어마하게 많은 클래스들이 로드타임에 로드되고 나서야 프로그램이 실행되고 실행되는 런타임에 SportsCar 클래스가 로드되는것을 확인가능. ( 아래 확인 )
// 명령어 입력
neo@Neos-MacBook-Air hello-world % java -classpath ./out/production/hello-world -verbose:class Main
... 중략 ...
// Car 클래스 로드.
[0.029s][info][class,load] Car source: file:/Users/neo/workspace/java/hello-world/out/production/hello-world/
... 중략 ...
Hello world!
// 이 지점에서 SportsCar 클래스가 로드 됨.
[0.029s][info][class,load] SportsCar source: file:/Users/neo/workspace/java/hello-world/out/production/hello-world/
Sports car move!!!
[0.029s][info][class,load] java.lang.Shutdown source: shared objects file
[0.029s][info][class,load] java.lang.Shutdown$Lock source: shared objects file
neo@Neos-MacBook-Air hello-world %
Q. 왜 SportsCar 클래스는 런타임 중간에 로드되는걸까?
A. 다형성의 원리를 생각해보면, 상위 클래스 (interface) 인 Car는 구체화된 클래스로 객체를 전달 받아야함. 그런데 프로그램이 실행되며 실행문이 해석되기 전까지 JVM은 Car에 SportsCar가 올지 Sedan이 올지 알 수 없다. 즉, 로드타임이 어떤 클래스를 로딩할지 결정 할 수 없다. 따라서 이 때 SportsCar 클래스는 런타임 중에 로딩된다.
참고 : 다형성이란.
1. 다형성의 개념 :
- 다형성은 객체 지향 프로그래밍(OOP)의 핵심 개념 중 하나로, 하나의 객체가 여러 형태를 가질 수 있는 능력을 의미함. 이는 같은 Interface나 부모 클래스를 공유하는 객체들이 동일한 메서드를 호출하더라도 각 객체의 특성에 맞게 다른 방식으로 동작할 수 있게 해줌.
2. 자바에서의 다형성 종류 :
- 컴파일 타임 다형성 ( 정적 다형성 ) : 메서드 오버로딩 (Method Overloading)
- 런타임 다형성 ( 동적 다형성 ) : 메서드 오버라이딩 (Method Overriding)
- Interface를 통해서도 다형성을 구현할 수 있다.
'Computer Science > JAVA' 카테고리의 다른 글
디폴트 메서드, 추상 클래스와 인터페이스 (1) | 2024.11.20 |
---|---|
Java의 실행 엔진 (0) | 2024.11.20 |
Java의 컴파일 과정 (0) | 2024.11.20 |
컬렉션 프레임 워크 (1) | 2024.11.20 |
동기 Async 와 비동기 ASync (1) | 2024.11.18 |