Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

자바(Java) 클래스의 정적 멤버, JVM이 읽는 순서와 단계


정적(static) 변수는 클래스가 로딩되는 시점, 즉 정적 블록이 실행되기 이전에 이미 생성됩니다. 정적 블록의 주된 목적은 바로 이 정적 변수에 값을 할당하는 것입니다.

정적 변수는 해당 클래스의 모든 인스턴스가 공유하는 값을 저장하며, 정적 블록은 클래스가 처음 로딩될 때 단 한 번 실행되는 코드 영역입니다. 따라서 클래스 로딩 시점에 반드시 수행되어야 하는 초기화 로직이 있다면, 그 로직을 정적 블록 안에 작성해야 클래스가 로딩될 때 자동으로 실행됩니다.

JVM이 클래스의 정적 멤버를 읽는 3단계

  • 1단계: 위에서 아래 방향(top to bottom)으로 정적 멤버를 식별합니다.
  • 2단계: 위에서 아래 방향으로 정적 변수 값 할당과 정적 블록을 실행합니다.
  • 3단계: main 메서드를 실행합니다.

예제 코드

public class StaticFlow {
    static int firstNumber = 10;
    static {
        firstMethod();
        System.out.println("first static block");
    }
    public static void main(String[] args) {
        firstMethod();
        System.out.println("main method executed");
    }
    public static void firstMethod() {
        System.out.println(secondNumber);
    }
    static {
        System.out.println("second static block");
    }
    static int secondNumber = 20;
}

실행 결과

0
first static block
second static block
20
main method executed

실행 결과 분석

첫 번째 출력값이 20이 아니라 0으로 나오는 점이 의아할 수 있습니다. 그 이유는 JVM이 정적 멤버를 처리하는 방식 때문입니다.

  1. JVM은 먼저 클래스 전체를 훑으며 firstNumber, secondNumber 등 모든 정적 멤버를 위에서부터 아래로 식별만 해둡니다. 이 시점에는 아직 값이 할당되지 않았습니다.
  2. 이후 다시 위에서부터 아래로 firstNumber = 10을 할당하고, 첫 번째 정적 블록을 실행합니다. 이 블록 안에서 호출된 firstMethod()secondNumber를 출력하는데, secondNumber = 20은 아직 실행되지 않았으므로 int 타입의 기본값인 0이 출력됩니다.
  3. 그다음 두 번째 정적 블록이 실행되고, secondNumber = 20이 할당됩니다.
  4. 마지막으로 main 메서드가 실행되면 이번에는 secondNumber에 20이 이미 할당된 상태이므로 20이 출력됩니다.

이처럼 정적 멤버의 식별실행(할당)이 서로 다른 단계에서 이루어진다는 점을 이해하면, 정적 블록과 정적 변수의 실행 순서를 정확히 예측할 수 있습니다.