본문 바로가기
Back-end

static lazy 로딩

by 신재권 2023. 8. 19.

상황 가정 및 목표

public class Test {
	static Test instance;

	public Test() {
		System.out.println("Test 생성자 호출");
	}

	static {
		System.out.println("Test.static 블록 초기화");
	}

	private static class InstanceHolder {
		private static final Test INSTANCE = new Test();

		static {
			System.out.println("InstanceHolder.static 블록 초기화");
		}
	}

	public static Test getInstance() {
		System.out.println("getInstance() 호출");
		return InstanceHolder.INSTANCE;
	}

}
public class Main {

	public static void main(String[] args) {
		System.out.println("프로그램 시작");

		Test test = Test.getInstance();

		System.out.println("프로그램 종료");
	}
}

클래스홀더를 사용한 lazy loading 방식으로 static 객체를 초기화할 때 어떤 방식으로 로딩이 되는가를 알아보기 위해 작성한 코드이다.

이를 통해 얻으려는 목표는 다음과 같다.

  1. 클래스로딩이 어떤 순서대로 진행되는지
  2. 메모리관점에서

실행 과정

아래 과정 대로 진행할 예정이다.

  1. 프로그램 실행
  2. main 메서드에서 Test.getInstance() 호출
  3. 프로그램 종료

실행 결과

실행 결과는 다음과 같다.

프로그램 시작
Test.static 블록 초기화
getInstance() 호출
Test 생성자 호출
InstanceHolder.static 블록 초기화
프로그램종료

클래스로딩 과정

클래스로딩 과정을 함께 보면 다음과 같다.

프로그램 시작
[0.077s][info][class,load] 소스코드폴더.Test source: file:소스코드폴더/src/
Test.static 블록 초기화
getInstance() 호출
[0.077s][info][class,load] 소스코드폴더.Test$InstanceHolder source: file:소스코드폴더/src/
Test 생성자 호출
InstanceHolder.static 블록 초기화
프로그램 종료

위 결과로 정리해보면 다음과 같다.

  1. Main의 main 메서드 실행
  2. Test test = Test.getInstance() 실행
  3. Test 클래스를 참조했으므로, 클래스로더에 의해 Test 클래스 로딩
  4. Test 클래스로딩 후, 초기화 단계 실행(static블록)
  5. Test 클래스가 로딩 완료되었으므로, Test 관련 사용 준비 완료
  6. getInstance() 시작
  7. static inner 클래스인 InstanceHolder 클래스 로딩 됨
  8. 내부에 static 객체인 INSTANCE, Test 생성자 호출 후, 초기화됨
  9. static 블록 초기화 진행
  10. 프로그램 종료

위 과정으로 진행된다.

내부 static 클래스 참조만 있을시?

만약 외부 참조가 없이, 내부 static 클래스만 사용하면 어떻게 될까?

public class Test {

	public static class TestInner{

		public static TestInner inner = new TestInner();

		public void method() {
			System.out.println("inner.method() 실행");
		}
	}
}
public class Main {

	public static void main(String[] args) {
		Test.TestInner testInner = new Test.TestInner();
		testInner.method();
	}
}
[0.084s][info][class,load] flab.test.Test$TestInner source: file:소스코드폴더
[0.084s][info][class,load] java.lang.StringUTF16 source: shared objects file
[0.085s][info][class,load] java.lang.Readable source: shared objects file
[0.085s][info][class,load] java.nio.CharBuffer source: shared objects file
[0.085s][info][class,load] java.nio.HeapCharBuffer source: shared objects file
[0.085s][info][class,load] java.nio.charset.CoderResult source: shared objects file
inner.method() 실행

위 두개의 코드 실험으로 다음 결과를 알아 냈다.

  • static inner 클래스의 클래스로딩은 내부 클래스가 참조될때 진행된다. 즉, 외부랑 별개 취급된다.

'Back-end' 카테고리의 다른 글

2023.08.20 TIL  (0) 2023.08.20
2023.08.19 TIL  (0) 2023.08.19
정적 vs 동적 in Java  (0) 2023.08.18
클래스 로더  (0) 2023.08.18
static  (0) 2023.08.16