JAVA

클래스는 언제 로딩될까

se0nghyun2 2023. 4. 10. 16:26

클래스 로딩?

클래스 로더가 .class파일을 찾아 JVM의 메모리에 올려놓는 과정을 의미한다.

 

로딩 종류

 1. 로드타임 동적 로딩

 2. 런타임 동적 로딩

 두 로딩에 대한 설명은  JVM 동적 클래스 로딩 (tistory.com) 블로그를 참고 바랍니다.

 

클래스 로딩 시점

  • 클래스의 인스턴스 생성
  • 클래스의 정적 메소드 호출
  • 클래스의 정적 변수 사용 (final x) ---> ? 타입에 따라 달랐다. String, 정의한 클래스 두개로 테스트 진행!
  • 데이터타입이 클래스 타입인 경우로 정적 변수 사용(final 유무 관계없이)

클래스 로딩 확인 방식( 나는 CMD창에서 진행함 )

1. java파일 컴파일
2. java -vervbose:class class파일명

<예시>
javac Main.java
java -vervbose:class Main

 

1. 클래스의 인스턴스 생성

public class Main {
    public static void main(String[] args) {
    	//클래스 인스턴스 생성
        TestClass testClass = new TestClass();
    }
}

class TestClass{
    public String test;
}

 

 

TestClass 로드 확인

 

 

 

2. 클래스의 정적 메소드 호출

public class Main {
    public static void main(String[] args) {
        Singleton.getInstance() //정적메소드 호출
    }
}

class Singleton{

    //정적 메소드
    static void getInstance(){
        System.out.println("정적메소드 호출!");
    }
}

 

Singleton클래스 로드 확인

 

 

3. 클래스의 정적 변수 사용(final 키워드 사용 X)

public class Main {
    public static void main(String[] args) {
        System.out.println(Singleton.INSTANCE); //정적 변수 사용
    }
}

class Singleton{
    //정적 변수
    static Singleton INSTANCE = new Singleton();
}

 

Singleton클래스 로드 확인

 

 

 

4.  클래스의 정적 변수 사용(final 키워드 사용)

클래스 로딩 시점 중 final키워드를 사용하면 클래스가 로딩되지 않는다는 글을 봐 눈으로 직접 확인해 보려 한다.

 

테스트케이스1) final 키워드 사용 && 클래스타입 변수

테스트케이스2) final 키워드 사용 && String형 변수(기본형으로 생각하면 될 듯)

 

결론부터 말한다면,

class타입인 경우 Singlton 클래스 호출 O

String타입인 경우 Singlteon 클래스 호출 X

컴파일된 클래스 파일을 디컴파일한 부분을 자세히 봐보자.

 

 

  4.1 class타입

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

class Singleton{
    //fianl 선언된 클래스타입 정적 변수
    static final Singleton INSTANCE = new Singleton();
}

 

클래스파일을 디컴파일해봄

 

  4.2 String 타입

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

class Singleton{
    //fianl 선언된 String형 정적 변수
    static final String INSTANCE = "test";
}

 

 

클래스파일을 디컴파일!!! 어라? test로 하드코딩되어있네??

 

엥???

String인 경우 코드상과 컴파일된 내용을 디컴파일한 내용과 다르다!!!!!!  System.out.println("test") ???

난 분명 코드 작성 시 System.out.println(Singlton.instacne)로 적었는데?

컴파일 되고 보니 값으로 바껴있다...?

아! 컴파일 시점에 Singleton.INSTACNE를 "test"로 바꿨구나!!!!!!


 

위 두 테스트 케이스를 결론으로 이야기를 해본다면,

* String의 경우는 Sinlgton클래스를 로딩하지도 않으며, 컴파일 시점에서 어딘가에 참조하는 상수(Singlton.Instance)를 값("test)으로 바로 할당하는 것으로 보인다.  (참고. final로 선언된 상수 컴파일에 관하여 (tistory.com))

 

* 이와 반대로, class타입의 경우는 singlton클래스를 로딩하며, 컴파일 시점엔 기존코드와 컴파일시점에서의 코드가 동일하다.

 

final키워드를 사용하면 클래스가 로딩되지 않는다???

아니다.  final키워드를 사용해도 데이터 타입에 따라 클래스 로딩이 결정된다.


 

 

참고

클래스는 언제 로딩되고 초기화되는가? (feat. 싱글톤) (velog.io)