여기 Java로 작성된 코드가 하나 있다.
public class Main{
public static void main(String[] args){
System.out.println("hello world!");
}
}
Java 환경에서 해당 코드를 어떻게 실행하는지 알아보자.
Java에서의 프로그램 실행 과정
- Java로 작성된 코드를 javac(Java 컴파일러)를 이용, Java 바이트 코드로 컴파일 한다.
- 컴파일된 Java 바이트 코드들은 ClassLoader(클래스 로더)에 의해 Runtime Data Area(런타임 데이터 영역)에 로드한다.
- Execution Engine(실행 엔진)이 메모리에 로딩된 바이트 코드를 기계어로 바꾸어 명령어 단위로 실행 한다.
1. javac 컴파일
- Java Source(
.java
)는 javac(Java 컴파일러)에 의해, 자바 코드 파일(.java
)에서 자바 바이트 코드(.class
)로 컴파일 된다
2. ClassLoader(클래스 로더)
- 컴파일된 바이트코드는 JVM의 클래스 로더에 전달된다.
- 클래스 로더는 애플리케이션 런타임 중 필요한 클래스 파일들을 동적으로 Runtime Data Area(런타임 데이터 영역 = JVM의 메모리)에 로드한다
- 즉, 실행 중에 필요한 클래스 파일을 메모리에 올리는 역할
3. Execution Engine(실행 엔진)
- 실행 엔진은 클래스 로더를 통해 런타임 데이터 영역에 배치된 바이트 코드들를 명령어 단위로 읽어서 실행한다.
- 자바 바이트 코드는 기계가 바로 수행할 수 있는 언어보다는 인간이 읽기 편한 언어에 가깝기 때문에, 실행 엔진은 자바 바이트코드들을 JVM 내부에서 기계가 실행 할 수 있는 형태로 변경한다.
이때 JVM은 인터프리터와 JIT(Just-In-Time)컴파일러를 사용한다.
인터프리터
- 인터프리터는 바이트 코드 명령어를 하나씩 읽어서 네이티브 코드로 변환하고 실행한다
- 인터프리팅 방식은 해석은 빠르나, 실행시간이 길고 느리다
JIT(just-in-time) 컴파일러
- JIT 컴파일러는 인터프리터의 단점(= 실행시간이 느림)을 보완하기 위해 사용 한다
- JIT 컴파일러는 자주 사용되는 클래스나 메소드의 바이트 코드 전체를 컴파일 하여 네이티브 코드로 변환
- 해당 네이티브 코드를 캐시에 보관하며, 캐시에 보관된 네이티브 코드는 이후 향상된 성능으로 빠르게 수행