Java - Class Loader에 대하여 (In JVM)

Tae Yun Choi·2023년 4월 6일
0

개발새발 Java

목록 보기
1/4
post-thumbnail

얼마 전, Enum을 사용하다 순환참조 에러를 겪은 일이 있었다.
해당 과정에서 Java의 동적로딩에 알게 되었고,
깊숙하게 숨어있던 Class Loader에 대해 알아보려 한다.

Dynamic Loading (동적로딩)

💡 자바는 동적로딩을 지원한다

동적로딩이란?

프로그램 실행 시에 모든 클래스가 로드되는 것이 아닌,
해당 클래스가 필요한 시점에 클래스를 로드한다.

그렇다면 동적로딩은 누가해줘?

JAVA는 JVM을 통해서 실행된다.
JVM은 기본적으로 Garbage Collector, Class Loader, Execution Engine, Runtime Data Area로 이루어져 있고, ClassLoader라는 녀석이 동적로딩을 가능케 해준다
JVM에 대해서는 다음에 알아보고
오늘은 ClassLoader에 대해 알아보자

Class Loader의 역할

  • Java를 통해 개발을 하게 되면 .java 라는 파일이 생성된다.
  • 해당 파일은 컴파일러에 의해 컴퓨터가 읽을 수 있는 바이트 코드로 변환하게 되고, 그 파일이 바로 .class이다.
  • 이렇게 컴파일 된 바이트코드를 Class Loader가 메모리영역으로 옮겨주게 된다.

Class Loader의 종류

  • BootStrap: jar 파일과 같은 핵심 시스템 클래스를 로딩한다.
  • Extension: 확장 프로그램을 로드한다
  • Application: 직접 만든 어플리케이션의 jar파일을 로드한다

jar파일이란?

동작 순서

💡 Class Loader에 의해 .class 파일은 Loading, Linking, Initialization이라는 세단계를 거쳐서 메모리영억으로 로드된다.
  1. 런타임 과정 중 해당 바이트 코드를 필요로 하는 부분을 만나면 동적로딩이 시작된다.
    • 필요로 하는 부분은 변수에 접근, 클래스에 접근하는 부분으로 생각하면 된다.
  2. Loading : BootStrap → Extension → Application 순으로 해당 파일을 찾는다.
  3. Linking : 로드된 파일에 에러가 있는지 확인하고, 정적 멤버 변수들에 메모리 할당 및 기본값으로 세팅합니다. 그 후 참조객체들 또한 세팅합니다.
  4. Initialization : 최종단계로 모든 정적 변수들에 코드로 작성된 값들이 할당되고, 정적 블록이 실행됩니다.

예시

public class Main {
    public static void main(String[] args) {
        System.out.println("프로그램을 시작합니다");

        System.out.println("프로그램이 시작됐어요");

        A a = new A();

        System.out.println("프로그램이 동작 중이에요");

        System.out.println("프로그램을 종료합니다");
    }
}

class A {
    static {
        System.out.println("안녕하세요 A의 정적 블록이에요");
    }

    {
        System.out.println("안녕하세요 A의 인스턴스 블록이에요");
    }

    public A () {
        System.out.println("안녕하세요 A의 생성자에요");
    }
}

class B {
    static {
        System.out.println("안녕하세요 B의 정적 블록이에요");
    }

    {
        System.out.println("안녕하세요 B의 인스턴스 블록이에요");
    }

    public B () {
        System.out.println("안녕하세요 B의 생성자에요");
    }
}

/**
* Output
* 프로그램을 시작합니다
* 프로그램이 시작됐어요
* 안녕하세요 A의 정적 블록이에요
* 안녕하세요 A의 인스턴스 블록이에요
* 안녕하세요 A의 생성자에요
* 프로그램이 동작 중이에요
* 프로그램을 종료합니다
/

위 코드에서 바이트코드를 필요로 하는 부분을 만난 순간은 A생성자에 접근하는 순간이다. 프로그램의 시작을 알리는 출력문들을 통해 A에 접근할 때까지 로드되지 않는 모습을 볼 수 있다. 또한, B에 접근을 하지 않았기에 클래스 B의 로드는 이루어지지 않은 것으로 보인다.

출처

profile
hello dev!!

0개의 댓글