Complie Time
❗complie time이란?
자바 소스 코드가 컴파일러에 의해 바이트 코드로 변환되는 시점으로 소스 코드의 문법이 올바른지 확인 하고, 변수 및 함수의 타입이 바르게 사용되었는지 확인한다.
또한 컴파일러가 가능한 최적화를 수행하여 효율적인 코드로 생성하게 된다. 이때 문법이나 타입, 참조 오류를 범하지 않도록 해야 한다.
❗컴파일 과정
1. 자바 소스코드를 작성한다.
일반적으로 작성하는 자바 소스 코드를 작성한다.
for (int i = 2; i < 1000; i++) {
...
}
2. 자바 바이트 코드로 변환한다.
자바 바이트 코드란 하드웨어에서 실행할 수 있는 기계어가 아니라 JVM이 해석할 수 있는 중간 개념의 코드이다.
자바 컴파일러(javac)를 통해 소스 파일을 자바 바이트 코드로 변환하면
0: iconst_2
1: istore_1
2: iload_1
3: sipush 1000
...
위의 for문이 이런 형태로 변환된다.
이후 컴파일된 바이트 코드는 JVM의 클래스 로더에 전달된다
Run Time
❗Run Time이란?
컴파일된 프로그램이 실제로 실행되는 시점을 의미하며 이때 프로그램이 실행되면서 논리 구조를 파악하고, 메모리의 할당과 해제, 사용자나 파일의 입출력 작업이 수행된다.
이때는 NullPointerException, ArrayIndexOutOfBoundsException, IOException나 로직 에러 등이 발생할 수 있다.
public class Example {
public static void main(String[] args) {
int x = 10;
int y = 0;
int z = x / y; // 런타임 오류: ArithmeticException (0으로 나누기)
System.out.println("Result: " + z);
}
}
이 경우 컴파일 과정에선 문법이나 구문 상의 오류가 없기 때문에 바이트코드로 변환되지만,
런타임에선 0을 제수로 사용할 수 없기 때문에 ArithmeticException가 발생한다.
❗런타임 과정
1. class loader가 자바 클래스 파일(.class)를 JVM으로 로드
앞선 컴파일 과정에서 생성된 바이트 코드를 class loader가 JVM으로 로드한다.
2. class loader의 작동 과정
클래스 로더가 동적 로딩을 이용하여 필요한 클래스를 JVM의 메모리인 런테임 데이터 영역(Runtime Data Area)에 올린다. (모든 코드가 JVM과 링크됨)
세부 동작은 아래와 같다.
로드 | 필요한 클래스 파일을 JVM의 메모리에 로드 |
검증 | 자바 언어 명세 및 JVM 명세에 명시된대로 파일이 구성되어 있는지 검사 |
준비 | 클래스에 존재하는 필드, 메소드, 인터페이스 등등이 필요로 하는 만큼 메모리를 할당 |
분석 | 클래스의 상수 풀(Constant Pool) 내의 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경 |
초기화 | 클래스의 변수를 적절한 값으로 초기화 |
3. Execution Engine의 작동 과정
JVM 메모리에 적재된 바이트 코드를 명령어 단위로 하나씩 갖고와서 실행하며, 2가지 실행 방식이 존재
인터프리터: 명령어를 하나씩 수행하기 때문에 명령어 실행 단위 시간은 빠르지만 전체적인 실행 속도를 느림
JIT(Just-In-Time) 컴파일러: 바이트 코드 전체를 컴파일하여 기계어로 변환하며 자주 사용되는 바이트코드를 기계어로 미리 변환하여 성능을 향상시킴
4. Runtime Data Area의 구성
Method Area | 클래스(타입) 정보, 메소드 데이터, 상수 풀을 저장하는 메모리 영역 JVM과 생명주기를 동일하게 가지고, 모든 스레드가 공유하는 영역 |
Heap | 객체를 동적으로 할당하는 공간으로 모든 객체와 배열은 힙에 저장됨 모든 스레드가 공유하며 가비지 컬렉터(GC)에 의해 자동으로 관리됨 사용하지 않는 객체는 GC를 통해 메모리 해제 |
Stack | 메소드 호출과 관련된 프레임을 저장 각 스레드별로 생성되며 메소드 호출과 생명주기를 동일하게 하는 영역 로컬 변수, 프레임(메소드 호출 정보), 연산 스택, 동기화 정보 등을 포함 |
PC(Program Counter) Register | 현재 실행 중인 JVM 명령의 주소를 가리키는 레지스터 각 스레드마다 별도의 PC 레지스터를 가지며 JVM 명령의 실행 흐름을 제어 |
Native Method Stack | 네이티브 메소드 호출에 사용되는 스택 C, C++로 작성된 네이티브 코드를 실행할 때 사용 JNI(자바 네이티브 인터페이스)를 통해 네이티브 메소드를 호출할 때 사용 |
5. Grabage Collector
참조되지 않는 객체들을 탐색하여 삭제하고, 삭제된 객체의 메모리를 반환하는 역할을 하며 이를 통해 Heap영역의 공간을 확보한다.
'🔻Language > Java' 카테고리의 다른 글
[Java] 동일성(identity)와 동등성(equality) (0) | 2024.11.16 |
---|---|
[Java] JVM이란 (0) | 2024.07.18 |
[Java] 두 날짜 사이의 차이 계산하기 (0) | 2023.02.24 |
[Java] 현재 날짜, 시간 불러오기 (0) | 2023.01.03 |
[Java] 문자열 랜덤 생성 (0) | 2022.12.23 |