Unicorns

All the things

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JavaStudy] - Class Loader(클래스 로더) in JVM
    Java 2021. 9. 29. 10:02

    Class Loader

    : 런타임 시 컴파일 된 .class 파일을 메모리에 로딩하는 역할을 수행한다.

     

     

    로딩, 링크 , 초기화 순으로 진행된다.

     

     

    Loading

    클래스 로더가 .class 파일을 읽고 그 내용에 따라 적절한 바이너리 데이터를 만들고 "메소드" 영역에 저장

    이때 메소드 영역에 저장하는 데이터는 다음과 같다.

     

    - FQCN(Fully Qualified Class Name) :  클래스가 속한 모든 패키지명을 모두 포함하는 이름

    - 클래스 , 인터페이스, ENUM

    - 메소드와 변수

     

    로딩이 끝나면  해당 클래스 타입의 Class 객체를 생성하여 "힙" 영역에 저장

     

     

    로딩 과정

    1. 우선 클래스가 메모리에 로드되었는지 확인 한다. (ClassLoader 클래스의 findLoadedClass() 메서드)

     

    2. 클래스가 메모리에 로드되어 있다면 실행을 진행한다.

     

    3. 클래스가 메모리에 로드되어 있지 않으면 JVM은 ClassLoader Sub Sysytem에 해당 클래스를 로드하도록 요청 하고

        (loadClass 메서드)  ClassLoader 하위 시스템은 그 역할을 Application ClassLoader에게 넘긴다.

     

    4. 클래스 로딩 요청을 받은  Application ClassLoader는 스스로 직접 로딩하지 않고 Extension ClassLoader 에게 위임한다.

     

    5. 클래스 로딩 요청을 받은 Extension ClassLoader는 스스로 직접 로딩하지 않고 Bootstrap ClassLoader 에게 위임한다.

     

    6.  Bootstrap ClassLoader는  rt.jar 에서 요청한 클래스를 찾은 뒤, 만약에 있으면 로딩 후 반환하고 없으면 Extension ClassLoader에게 위임한다.

     

    7. Extension ClassLoader는 jre/lib/ext 폴더나 java.ext.dirs 환경 변수로 지정된 폴더에서 요청한 클래스를 찾은 뒤, 만약에 있으면 로딩 후 반환하고 없으면 Application ClassLoader에게 위임한다.

     

    8.  Application ClassLoader는 클래스패스에서 요청한 클래스를 찾은 뒤, 만약에 있으면 로딩 후 반환하고 없으면

    ClassNotFoundException 이 발생한다. 

     

     

     

    java.lang.ClassLoader  (ClassLoader 클래스)

     

    • Bootstrap Classloader 

       모든 ClassLoader의 부모로 rt.jar 파일을 로드하는 데 rt.jar 파일은  JDK 설치경로/jre/lib 위치에 있다.

       rt.jar 에서 rt는 runtime 을 의미하는데 자바 프로그램을 실행하는데 필요한 클래스들이 들어있는 파일이다.

       대표적으로 java.lang 패키지 안에 있는 클래스들이 있다. 이 클래스들은 ClassLoader 최상위 부모이기 때문에 

       import를 하지 않고도 사용할 수 있다.  ex) java.lang.String -> String 

       rt.jar 파일은 크기가 너무 크기 때문에 java9 부터는 rt.jar 대신  작은 모듈로 나누어졌다.

    • Extension(or Platform) ClassLoader

        Bootstrap ClassLoader 의 자식으로 jre/lib/ext 나 java.ext.dirs 에 위치한 자바의 확장 클래스를 로드한다.

       

    • Application(or System) ClassLoader

           Extension ClassLoader의 자식으로 classpath 환경 변수로 지정된 클래스를 로드한다.

     

    코드

    public class Main {
        public static void main(String[] args) {
            System.out.println(Main.class.getClassLoader());
        }
    }

    출력

    출력 결과를 보면 Application ClassLoader라는 것을 알 수있다.

    public class Main {
        public static void main(String[] args) {
            System.out.println(Main.class.getClassLoader().getParent());
        }
    }

    getParent() 로 부모 클래스로더 출력

    Application ClassLoader의 부모인 PlatformClassLoader 에 대한 정보가 출력되었다.

    (예전에는 ExtensionClassLoader 로 불렀지만, 요즘은 PlatformClassLoader 라고 한다. )

     

     

    PlatformClassLoader의 부모를 출력해보자

    public class Main {
        public static void main(String[] args) {
            System.out.println(Main.class.getClassLoader().getParent().getParent());
        }
    }

    Bootstrap ClassLoader에 대한 정보가 출력될 줄 알았는데

    ??? null 값이 출력되었다.

     

    Bootstrap ClassLoader는 java 아닌 native code로 구현되어 있기 때문에 JVM마다 다 다르게 동작하는데,

    그로 인해 자바에서 참조하여 출력할 수 없기 때문이다.

     

     

     

    class loading 의 3가지 원칙

     

    • delegation :

     클래스를 메모리에 로드하기 위해 ClassLoader 하위 시스템에 요청하면 클래스로더의 윗 방향(부모)으로 클래스 로딩을 위임한다. 

    • visibility :

        부모가 로드한(상위) 클래스는 모든 자식(하위) loader가 볼수 있지만 자식(하위)이 로드한 클래스는 부모(상위) loader가 볼수 없다

     

    예)  하위 클래스 로더인 애플리케이션 클래스로더가 부트스트랩 클래스로더(최상위 로더)에 의해 로딩된 String.class를 볼 수 없다면 애플리케이션은 String.class를 사용할 수 없을 것이다. 따라서 하위에서 상위를 볼 수 있어야 애플리케이션이 제대로 동작할 수 있다.

    • uniqueness:

     클래스는 로딩 과정 중에 딱 한번 로드된다.

    즉, 하위 클래스로더는 상위 클래스로더가 로딩한 클래스를 다시 로딩하지 않게 해서 로딩된 클래스의 유일성을 보장하는 것이다.

     

     

    Linking

    verify

    • 컴파일이 잘 되었는지 확인하는 절차이다.
    • .class 파일 형식이 올바른지 여부를 확인한다.
    • CLassLoader sub system안에 위치한  ByteCode verifier 가 위의 역할을 수행한다.

    prepare

    • 메모리를 준비하는 단계
    • 이 단계에서 jvm은 클래스 또는 인터페이스의 정적 변수를 메모리에 로드하고 기본 값을 설정한다.

    resolve

    • compile time 에 자바 클래스는 다른 클래스의 실제 주소 값을 알지 못한다.
    • 실제 주소값 대신 symbolic references 가 대체한다.
    • resolve 단계에서 런타임 constant pool 에 symbolic references의 구체적인 값을 지정한다.

     

     

    Initializtion

     모든 정적 변수가 기본 값에서 지정된 값으로 초기화 되고 block이 위에서 아래로, 부모에서 자식으로 실행된다.

     

     

     

     

     

     

     

    REFERENCE 

    https://frugalisminds.com/java-class-loaders-internal-working/
    https://www.geeksforgeeks.org/classloader-in-java/
    https://codepumpkin.com/class-loader-subsystem-jvm-internals/#Linking
    https://topic.alibabacloud.com/a/java-virtual-machines-symbolic-references-and-direct-font-colorredreferencefont-understanding_1_27_30293654.html
    https://homoefficio.github.io/2018/10/13/Java-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A1%9C%EB%8D%94-%ED%9B%91%EC%96%B4%EB%B3%B4%EA%B8%B0/
    더 자바, 코드를 조작하는 다양한 방법 - 백기선님

     

    댓글

Designed by Tistory.