
이글은, 오라일리 사의 Optimizing Java 책을 참고하여, 정리한 내용이다.
인터프리팅 : 소스 코드나 중간 코드를 직접 실행하는 방식입니다. 인터프리터는 프로그램의 명령어를 한 줄씩 읽고 실행합니다. 이 과정에서 소스 코드나 바이트코드를 직접 해석하고 수행하는 역할을 합니다.
클래스 로딩 : JVM에서 클래스 파일을 읽어들여 메모리에 로드하는 과정을 말합니다. 이 과정은 JVM의 클래스 로더에 의해 수행되며, 클래스의 바이트코드를 메모리에 적재하고, 클래스의 정의를 관리하여 프로그램 실행 중 사용할 수 있도록 합니다.
JVM은 스택 기반의 해석 머신 입니다. 레지스터는 없지만, 일부 결과를 실행 스택에 보관하며, 이 스택의 맨 위에 쌓인 값들을 가져와 계산을 진행합니다.
JVM 인터프리터(해석기)는, 평가 스택을 이용해 중간 값들을 담아두고 가장 마지막에 실행된 명령어와 독립적으로 프로그램을 구성하는 옵코드(Operation Code)를 하나씩 순서대로 처리하는 While 루프 안의 Switch문 입니다.
HelloWorld 라는 아주 간단한, Java 코드를 실행한다고 가정합니다. 자바 애플리케이션을 실행하면, 다음과 같은 순서를 가질 것입니다.
이때, 애플리케이션의 진입점은 HelloWorld.class에 있는 main() 메서드 이다. 제어권을 이 클래스로 넘거야 main 로직이 실행 될 수 있다.
따라서 이 helloWorld 클래스를 로딩 시킬 필요가 있습니다.
Java는 동적 로드, 즉 컴파일 타임이 아니라 런타임(바이트 코드를 실행할 때)에 클래스를 링크하고 로드하는 특징이 있습니다.
이때 자바 클래스 로딩(classloading) 메커니즘이 관여 합니다. 자바 클래스로더에는 3가지가 있습니다.
먼저 부트스트랩 클래스 로더 부터 실행되게 됩니다.
public class Main {
public static void main(String[] args) {
System.out.println("Starting main method");
// 10초 동안 대기
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Test 클래스 사용
Test test = new Test(); // 이 시점에서 Test 클래스가 로드됩니다.
test.sayHello();
}
}
class Test {
public void sayHello() {
System.out.println("Hello from Test class!");
}
}
이 코드로 이뤄진 Application을 실행하게 되면 다음과 같은 순서를 가지게 됩니다.
컴파일은 완료 되었다고 생각합니다.
초기화단계
실행단계
Method Area에 클래스가 로드 되어있는지 확인.애플리케이션 클래스로더에 Main 클래스 로드 요청애플리케이션 클래스로더 -> 부트스트랩 클래스로더에 요청 위임.부트스트랩 클래스로더에서 클래스 확인.애플리케이션 클래스로더로 요청 전달애플리케이션 클래스로더에서 요청 접수 및 로딩main() 메서드가 실행되며, Sleep() 까지 진행 완료.Method Area에 클래스가 로드 되어있는지 확인.이때, 8번 과정에서
애플리케이션 클래스로더가 클래스를 확인 하지 못한다면ClassNotFoundException을 발생시킨다.
3번 과정에서
Method Area에 클래스가 로드되어있다면, 해당 클래스를 사용한다.