JAVA

클래스 로더란?

경딩 2025. 3. 24. 13:29

jvm 내부에서 자바 바이트코드를 전달받아 동작하는 클래스 로더에 대해 알아보자!

 

클래스 로더의 개념

자바는 동적 로드, 즉 컴파일 타임이 아니라 런타임(바이트코드를 실행할 때) 에 클래스를 링크하고 로드하는 특징을 가진다. 자바의 클래스 로딩은 클래스 참조 시점에 JVM 에 코드가 링크되고, 실제 런타임 시점에 로딩되는 동적 로딩을 거친다.

자바는 클래스 로딩은 클래스 참조 시점에 JVM 에 코드가 링크되고, 실제 런타임 시점에 로딩되는 동적 로딩을 거진다.

 

런타임에 동적으로 클래스를 로딩한다는 것은 JVM 이 미리 모든 클래스에 대한 정보를 메소드 영역에 로딩하지 않았다는 것을 의미합니다.

 

JVM 내에서 자바 바이트코드를 전달받는 클래스 로더가 자바가 동적으로 로드될 수 있도록 해주는 소프트웨어입니다. 정리하자면, 클래스 로더는 런타임 중에 JVM의 메소드 영역에 동적으로 Java 클래스를 로드하는 역할을 합니다.

 

클래스 로더

 

클래스 로더 시스템

  • .class 에서 바이트 코드를 읽고 JVM의 메모리 영역인 Runtiem Data Areas(stack, pc, 네이티브.. 등)에 적절히 배치한다.
  • 바이트 코드는 말그대로 jvm 이 실행하기 위한 instruction 이다.
  • jvm 이 바이트 코드를 실행하면 자료구조가 생성된다.  
    • 로딩 : 바이트 코드를 클래스로 읽어오는 과정
    • 링크 : 레퍼런스를 연결하는 과정
    • 초기화 : static 값들 초기화 및 변수에 할당
  • 로더, 링크, 초기화  순으로 진행된다.
  • 로딩
    • 클래스 로더가 .class 파일을 읽고 그 내용에 따라 적절한 바이너리 데이터(JVM 이 관리하는 자료 구조 형태로 변환되어 메모리에 올라감.)를 만들고 "메소드" 영역에 저장. 
      • 즉 클래스 정보(바이트 코드 .class)를 메소드 영역에 저장
    • 이때 메소드 영역(메타스페이스)에 저장하는 데이터 
      • FQCN (Full Qualified Class Name) : 패키지 경로, 클래스이름
      • 클래스 파일과 클래스 | 인터페이스 | enum 의 관련 여부
      • 메소드와 변수 등의 정보
    • 메서드 영역이란 : 메서드 영역은 프로그램을 실행하는 데 필요한 공통데이터를 관리
    • 이 영역은 프로그램의 모든 영역에서 공유함.
    • 로딩이 끝나면 해당 클래스 타입의 Class 객체 (클래스 t 타입의 객체)를 생성하여 "힙" 영역에 저장
    • Solution solution = new Solution();
    • Class<? extends Solution> aClass = solution.getClass();
  • 링크
    • Verify, Prepare, Resolve(optional) 세 단계로 나눠져 있다.
    • 검증: .class  파일 형식이 유효한지 체크한다.
    •  Preparation: 클래스 변수(static 변수) 와 기본값에 필요한 메모리
    • Resolve: 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체한다.
  • 초기화
    • Static 변수의 값을 할당한다. (static 블럭이 있다면 이때 실행된다.)

클래스 로더의 종류

  • 클래스 로더는 계층 구조로 이뤄져 있으면 기본적으로 세가지 클래스 로더가 제공된다.
    • 부트 스트랩 클래스 로더 - JAVA_HOME\lib 에 있는 java.lang.*, java.util.* 등의 기본 API 클래스들을 제공한다.
      • 최상의 우선 순위를 가진 클래스 로더
    • 플랫폼 클래스로더 - JAVA_HOME\lib\ext 폴도 떠는 java.ext.dirs 시스템 변수에 해당하는 위치에 있는 클래스를 읽는다. (자바 9 는 module path을 사용해야함)
        Solution solution = new Solution();
        Class<? extends Solution> aClass = solution.getClass();
java --module-path /path/to/libs -m mymodule/com.example.Main

 

  • 애플리케이션 클래스로더 - 애플리케이션 클래스패스(애플리케이션 실행할 때 주는 -classpath 옵션 또는 java.class path 환경 변수의 값에 해당하는 위치)에서 클래스를 읽는다.
      ClassLoader classLoader = Solution.class.getClassLoader();
        System.out.println(classLoader);
        System.out.println(classLoader.getParent());
        System.out.println(classLoader.getParent().getParent()); // 최상위 부트스트랩 클래스 로더는 네이티브코드임. 참조해서 출력 불가
    }

 

  • 실행결과

 

classLodaers 파일을 확인하면  BOOT_LOADER, PLATFORM_LOADER, APP_LOADER 가 있는것을 확인할 수 있다.

 

 String append = VM.getSavedProperty("jdk.boot.class.path.append");

부트스트랩 로더는 해당 클래스 패쓰에 있는 클래스들만 읽어준다.

 

  PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER);

플랫폼 로더는 Boot 스트랩을 부모로만 설정했다.

String cp = System.getProperty("java.class.path");
if (cp == null || cp.isEmpty()) {
            String initialModuleName = System.getProperty("jdk.module.main");
            cp = (initialModuleName == null) ? "" : null;
        }
        URLClassPath ucp = new URLClassPath(cp, false);
        if (archivedClassLoaders != null) {
            APP_LOADER = (AppClassLoader) archivedClassLoaders.appLoader();
            setArchivedServicesCatalog(APP_LOADER);
            APP_LOADER.setClassPath(ucp);
        } else {
            APP_LOADER = new AppClassLoader(PLATFORM_LOADER, ucp);
            ArchivedClassLoaders.archive();
        }

 

APP_LODER 는 java 클래스 패스 또는 jdk 모듈 메인에서 값을 가져와 클래스 Path를 읽어준다.

 

직접 작성한 코드 99% 는 애플리케이션 클래스로더가 읽게 된다.

 

클래스로더의 동작 방식

JVM의 클래스 로더는 새로운 클래스를 로드해야할 때, 다음과 같이 동작하게 됩니다.

  • JVM의 Method Area에 클래스가 로드되어 있는지 확인한다. 만일 로드되어 있는 경우 해당 클래스를 사용한다.
  • Method Area에 클래스가 로드되어 있지 않을 경우, 시스템 클래스 로더에 클래스 로드를 요청한다.
  • 시스템 클래스 로더는 확장 클래스 로더에 요청을 위임한다.
  • 확장 클래스 로더는 부트스트랩 클래스 로더에 요청을 위임합니다.
  • 부트스트랩 클래스로더는 부트스트랩 Classpath(JDK/JRE/LIB) 에 해당 클래스가 있는지 확인한다. 클래스가 존재하지 않는 경우 확장 클래스로더에게 요청을 넘긴다.
  • 확장 클래스 로더는 확장 Classpath(JDK/JRE/LIB/EXT) 에 해당 클래스가 있는지 확인한다. 클래스가 존재하지 않는 경우 시스템 클래스 로더에게 요청을 넘긴다.
  • 애플리케이션 클래스로더는 시스템 Classpath에 해당 클래스가 있는지 확인한다. 클래스가 존재하지 않는 경우 ClassNotFoundException을 발생시킨다.

 


런타임 데이터 영역 (Runtime Data Area)

 

런타임  데이터 영역은 쉽게 말하면 JVM 의 메모리 영역 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역이다.

 

이때 Method Area 와 HeapAread 는 모든 쓰레드가 공유하는 영역이고 나머지 Stack Area, PC Register, Native Method Stack 은 각 쓰레드마다 생성되는 개별 영역이다. 

따라서 위의 그림을 좀 더 자세히 표현하자면 다음과 같이 도식이 된다.

 

 

더보기

클래스의 메타데이터는 한벌만 존재,

인스턴스는 각각의  클래스의 상태가 다 다르기 때문에 인스턴스마다 존재 

그거랑 별개로  클래스 t타입의 객체는 하나만 있으면 된다. 런타임에 클래스 정보를 얻기 위한 객체이기 때문이다

참고사항:

https://velog.io/@ddangle/Java-%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%A1%9C%EB%8D%94%EB%9E%80

 

'JAVA' 카테고리의 다른 글

Java 예외 처리, 제대로 알고 쓰자  (1) 2025.03.26
바이트코드 조작  (0) 2025.03.24
JVM, JDK, JRE 의 차이, JVM의 동작방식  (0) 2025.03.23
네트워크 - 프로그램1  (1) 2025.01.29
자바 - IO 기본 (buffer)  (1) 2025.01.28