클래스 파일 기본 구조
자바 클래스 파일은 기본적으로 클래스 선언과 멤버(필드와 메서드)로 구성됩니다.
예를 들어, Person이라는 클래스를 만든다면, 이 클래스는 아래와 같은 요소로 구성될 수 있습니다:
- 클래스 이름: 클래스 선언 부분으로 class Person {}처럼 작성됩니다.
- 필드: 클래스가 가지는 속성을 정의하며, 예를 들어 String name; int age;처럼 작성됩니다.
- 생성자: 객체 생성 시 호출되는 메서드로, 클래스와 이름이 동일하고 리턴 타입이 없습니다.
- 메서드: 클래스의 동작을 정의하는 함수들로, 예를 들어 public void greet() {}처럼 작성됩니다.
자바 클래스 파일 구조
클래스 파일은 크게 다음과 같은 구조로 구성됩니다.
- Magic Number: 파일의 시작 부분에 위치한 고유 값(0xCAFEBABE)으로, JVM이 이 파일이 자바 클래스 파일임을 인식하는 데 사용됩니다.
- 버전 정보: 자바 컴파일러의 버전을 기록합니다.
- 상수 풀(Constant Pool): 클래스, 메서드, 필드 등의 정보를 저장하는 영역입니다. 모든 클래스 파일의 참조 값이 상수 풀에 기록되며, 이는 런타임 시에 참조되는 다양한 정보를 포함합니다.
- 접근 제어자(Access Flags): 클래스가 public, final, abstract 등의 접근 제한자를 사용하는지 나타냅니다.
- 클래스 인덱스, 부모 클래스 인덱스, 인터페이스 인덱스: 각 클래스가 어떤 부모 클래스나 인터페이스를 가지고 있는지를 상수 풀의 인덱스로 기록합니다.
- 필드 정보: 클래스가 가지는 필드(멤버 변수)에 대한 정보를 저장합니다.
- 메서드 정보: 클래스가 가지는 메서드들에 대한 정보를 저장합니다.
- 속성 정보(Attributes): 클래스에 추가된 메타데이터로 디버깅 정보, 애노테이션, 소스 파일 이름 등의 다양한 정보를 포함합니다.
클래스 인덱스, 부모 클래스 인덱스, 인터페이스 인덱스
이 인덱스들은 상수 풀(Constant Pool)의 참조값을 이용해 클래스의 상속 관계를 나타내며, 클래스와 상위 클래스 및 인터페이스의 연결을 제공합니다.
- 클래스 인덱스: 해당 클래스 자체를 나타내는 상수 풀 인덱스를 가리킵니다. 이 인덱스를 통해 JVM은 해당 클래스의 이름을 확인합니다.
- 부모 클래스 인덱스: 부모 클래스의 상수 풀 인덱스를 가리키며, 클래스의 상속 관계를 나타냅니다. 모든 클래스는 단 하나의 부모 클래스만 가질 수 있고, 최상위 클래스는 java.lang.Object입니다.
- 인터페이스 인덱스: 클래스가 구현한 인터페이스 목록을 상수 풀 인덱스로 가리킵니다. 한 클래스는 여러 개의 인터페이스를 구현할 수 있기 때문에 여러 개의 인덱스가 포함될 수 있습니다.
실행 순서
자바 프로그램의 실행 순서는 보통 다음과 같습니다:
- main 메서드 실행: 자바 프로그램이 실행될 때 JVM은 main 메서드를 찾아 실행합니다. main 메서드는 프로그램의 시작점이며, 모든 실행이 여기서 시작됩니다.
- 객체 생성: new 키워드를 통해 클래스를 인스턴스화하여 객체를 생성합니다.
- 생성자 호출: 객체가 생성되면, 생성자가 호출되어 초기화 작업을 수행합니다.
- 메서드 호출: 생성 후, 필요한 메서드가 호출되어 프로그램이 동작합니다.
조금더 자세히 알아봅시다!
1. 클래스 로딩(Class Loading)
자바 프로그램이 실행되면 JVM은 먼저 필요한 클래스 파일을 로딩합니다. 클래스 로딩 과정에서 클래스 로더가 사용되며, 클래스 파일은 메모리에 적재됩니다. 이때 자바의 클래스 로더 계층 구조에 따라 클래스를 로딩하게 됩니다:
- Bootstrap ClassLoader: 가장 기본이 되는 클래스 로더로, java.lang.* 같은 표준 자바 API 클래스들을 로딩합니다.
- Extension ClassLoader: 확장 클래스들을 로딩하며, 주로 Java Extensions 디렉토리에 있는 클래스들을 담당합니다.
- Application ClassLoader: 애플리케이션이 정의한 클래스들을 로딩합니다. 일반적으로 사용자가 작성한 클래스들이 여기에 속합니다.
2. 링킹(Linking)
클래스가 메모리에 로딩되면, JVM은 해당 클래스를 실행하기 전에 세 가지 과정을 통해 클래스를 링크합니다:
- 검증(Verification): 바이트코드가 올바르고, 보안 위반이 없고, JVM 사양을 준수하는지 확인합니다. 잘못된 바이트코드가 있을 경우 실행되지 않습니다.
- 준비(Preparation): 모든 정적 변수(static variables)를 메모리에 배치하고, 기본값으로 초기화합니다.
- 해결(Resolution): 상수 풀에 있는 심볼릭 레퍼런스들을 실제 메모리 주소로 변경해 연결합니다.
3. 초기화(Initialization)
클래스 초기화 단계에서는 정적 초기화 블록과 정적 변수들이 선언된 순서대로 실행됩니다. 이 단계에서 실제로 클래스가 실행을 준비하게 됩니다.
- 정적 초기화 블록 실행: 클래스에 정의된 정적 초기화 블록이 있다면 이 블록이 실행됩니다.
- 정적 변수 초기화: 정적 변수들이 선언된 값으로 초기화됩니다.
4. main 메서드 호출
초기화가 완료되면 JVM은 main 메서드를 호출합니다. main 메서드는 자바 프로그램의 진입점(entry point)으로, 프로그램의 실행이 시작됩니다.
5. 객체 생성(Object Creation)
main 메서드나 다른 메서드에서 new 키워드가 호출되면, JVM은 힙 메모리에 객체를 생성하고, **생성자(Constructor)**를 호출합니다.
- 메모리 할당: 힙 메모리 공간에 객체에 필요한 메모리를 할당합니다.
- 생성자 호출: 객체가 생성되면, 해당 클래스의 생성자가 호출됩니다. 이 과정에서 필드들이 선언된 값으로 초기화되며, 부모 클래스가 있을 경우 부모 클래스의 생성자부터 순차적으로 호출됩니다.
6. 메서드 호출(Method Execution)
객체가 생성된 이후에는 프로그램이 해당 객체의 메서드를 호출하거나 main 메서드 내에서 작성된 코드가 실행됩니다. 메서드 호출은 스택 프레임을 생성하여 각 메서드의 실행 상태를 저장하고, 실행이 끝나면 스택 프레임을 제거하는 방식으로 관리됩니다.
- 스택 메모리 사용: 메서드가 호출될 때마다 JVM은 스택 프레임(Stack Frame)을 생성하고, 해당 메서드가 실행되면서 필요한 로컬 변수와 데이터를 저장합니다.
- 메서드 반환: 메서드가 종료되면 스택 프레임이 제거되고, 호출한 메서드로 제어가 반환됩니다.
7. 프로그램 종료
main 메서드를 포함한 모든 실행이 종료되면, JVM은 메모리에서 클래스를 언로드(unload)하고, 프로그램이 종료됩니다.
실행 순서 요약
- 클래스 로딩 -> 링킹 -> 초기화 -> main 메서드 실행 -> 객체 생성 -> 메서드 호출 -> 프로그램 종료
이상입니다!
'public void static main > Book' 카테고리의 다른 글
[대규모 시스템 설계 기초] 1장, 2장 (1) | 2025.01.06 |
---|---|
[JVM 밑바닥] 7장 클래스 로딩 메커니즘 (1) | 2024.11.17 |
[JVM 밑바닥] 3장 가비지 컬렉터와 메모리 할당 전략 -1 (0) | 2024.08.07 |
[JVM 밑바닥] 1장. 자바, 2장 자동 메모리 관리 (6) | 2024.07.25 |
[CISCO NETWORK] PART 1 - OSI 7 Layer (0) | 2023.02.16 |
댓글