자바(Java)는 플랫폼 독립성을 가지는 언어로, "Write Once, Run Anywhere"라는 철학 아래 설계되었습니다. 이를 가능하게 하기 위해 자바는 소스 코드를 중간 형태인 바이트코드(Bytecode)로 변환하고, 이 바이트코드를 JVM(Java Virtual Machine)이 실행하는 구조를 따릅니다. 자바 컴파일 과정을 설명하겠습니다.
1. 자바 컴파일 과정
자바 컴파일 과정은 크게 세 단계로 이루어집니다:
- 소스 코드 작성(Source Code Writing)
- 개발자가 .java 확장자를 가진 파일에 자바 소스 코드를 작성합니다.
- 컴파일(Compilation)
- javac 컴파일러를 통해 자바 소스 코드가 바이트코드로 변환됩니다.
- 결과물은 .class 파일로 저장됩니다.
- 실행(Execution)
- JVM이 바이트코드를 읽고 실행합니다.
- 실행 중 JIT(Just-In-Time) 컴파일러가 바이트코드를 네이티브 코드로 변환합니다.
2. 단계별 설명
2.1 소스 코드 작성
개발자는 자바 프로그래밍 언어의 문법을 사용하여 프로그램을 작성합니다. 이 코드는 .java 확장자를 가진 텍스트 파일에 저장됩니다.
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
- 파일 이름: 클래스 이름과 동일해야 하며, HelloWorld.java로 저장합니다.
- 문법 검사: 개발자는 코드 작성 중 IDE(IntelliJ, Eclipse 등)나 에디터를 통해 문법 오류를 확인할 수 있습니다.
2.2 컴파일 (javac 사용)
컴파일 과정에서 자바 소스 코드가 바이트코드로 변환됩니다. 이 과정은 다음과 같은 단계를 거칩니다 :)
2.2.1 구문 분석 (Lexical Analysis)
- 소스 코드를 토큰(token)으로 나눕니다.
- 키워드, 변수 이름, 리터럴 등을 식별하여 분석합니다.
- 예: public → 키워드, HelloWorld → 식별자(identifier).
2.2.2 구문 트리 생성 (Syntax Analysis)
- 토큰을 기반으로 구문 트리를 생성합니다.
- 자바 문법에 맞는지 확인하고, 오류가 있다면 컴파일을 중단합니다.
- 예: System.out.println이 올바른 호출 형태인지 검사합니다.
2.2.3 중간 표현 생성 (Intermediate Representation)
- 구문 트리를 기반으로 중간 표현(intermediate representation)을 생성합니다.
- 이 표현은 최적화를 용이하게 하기 위해 사용됩니다.
2.2.4 바이트코드 생성 (Bytecode Generation)
- .class 파일에 저장될 바이트코드를 생성합니다.
- 바이트코드는 플랫폼에 독립적이며 JVM이 이해할 수 있는 명령어로 구성됩니다.
- 예: System.out.println("Hello, World!") → JVM 명령어로 변환됩니다.
컴파일 명령 실행
컴파일 명령어를 사용하여 .class 파일을 생성합니다:
javac HelloWorld.java
컴파일 결과, 같은 디렉토리에 HelloWorld.class 파일이 생성됩니다.
2.3 실행 (JVM 사용)
JVM(Java Virtual Machine)은 .class 파일을 실행합니다. JVM은 다음 단계를 통해 프로그램을 실행합니다:)
2.3.1 클래스 로딩 (Class Loading)
- ClassLoader가 .class 파일을 읽어 JVM 메모리에 로드합니다.
- 클래스 간의 의존성을 확인하고 필요한 클래스도 함께 로드합니다.
2.3.2 바이트코드 검증 (Bytecode Verification)
- 로드된 바이트코드가 JVM 명세를 준수하는지 확인합니다.
- 보안 위협을 방지하기 위해 무효한 명령어나 메모리 접근이 없는지 검사합니다.
2.3.3 실행 엔진 (Execution Engine)
- 바이트코드를 실행하는 핵심 구성 요소입니다.
- 두 가지 주요 방식으로 실행합니다:
- 인터프리터(Interpreter): 바이트코드를 한 줄씩 읽고 실행합니다.
- JIT(Just-In-Time) 컴파일러: 실행 성능을 높이기 위해 바이트코드를 네이티브 머신 코드로 변환합니다.
2.3.4 네이티브 메서드 실행
- 네이티브 코드(Java로 작성되지 않은 코드)를 호출해야 할 경우 네이티브 메서드 라이브러리를 사용합니다.
- 예: C로 작성된 I/O 작업 수행.
3. 결과
위 과정을 통해 자바 프로그램은 작성한 코드가 실행되어 결과를 출력하게 됩니다. 예를 들어:
java HelloWorld
출력 결과:
Hello, World!
JIT 컴파일
- JIT 컴파일러는 실행 중 바이트코드를 네이티브 코드로 변환하여 실행 속도를 향상시킵니다.
- 동일한 코드가 반복 실행될 경우 최적화가 적용됩니다.
가비지 컬렉션 (Garbage Collection)
- JVM은 자동으로 메모리를 관리하며, 더 이상 참조되지 않는 객체를 제거하여 메모리를 확보합니다.
'IT 개발 라이프 > Back_End' 카테고리의 다른 글
Jackson 기반 JSON 유틸리티와 커스텀 ObjectMapper 적용하기 (0) | 2025.01.09 |
---|---|
디자인 패턴 이란? + 예시 (0) | 2025.01.03 |
자바 HashMap vs HashTable vs ConcurrentHashMap (1) | 2024.12.31 |
자바(JAVA) try-with-resources (0) | 2024.12.31 |
자바에서 Generic(제네릭)을 쓰는 이유 (1) | 2024.12.27 |