Java 동작 과정
전체적인 동작 과정은 컴파일 수행 -> 클래스 로딩 -> 메모리 할당 -> 바이트 코드 해석 및 실행 -> 가비지 컬렉션 -> 예외 처리 -> 프로그램 종료 과정을 수행합니다.
위 그림은 전체적인 자바의 실행 과정을 보여줍니다. 그럼 이제 조금씩 나누어서 과정을 살펴보겠습니다.
1. 컴파일 (Compile)
컴파일러 (Compiler)는 '해석기'라는 뜻으로 인간이 사용(이해)하는 고레벨언어를 기계가 이해할 수 있는 기계어(저 레벨 언어)로 해석해 주는 번역 프로그램입니다.
사람이 java언어로 Member라는 클래스를 만들면 IDE,Eclipse같은 IDE들은 자동 컴파일 기능을 갖추고 있어, 파일을 저장하는 순간 자동으로 컴파일을 수행합니다. 이렇게 자동으로 컴파일된. class 파일은 최종적으로 실행되는 파일은 아닙니다. java파일을 실행하기 위해서는 그 이후 과정을 거쳐야 합니다.
2. 클래스 로더 (Class Loader)
클래스 로더는 컴파일 된 자바의 클래스파일(*. class)을 동적으로 로드하고, JVM의 메모리 영역인 Runtime Data Area 안에 Method Area에 배치하는 작업을 수행합니다.
JVM : Java와 OS(운영체제) 사이에서 중개자 역할을 수행하며 Java가 OS에 구애받지 않고 독립적으로 작동이 가능합니다. 또한 가장 중요한 메모리 관리, Garbage collection을 수행합니다.
3. 메모리 할당 (Memory Allocation) - method area
Class Loader를 통해 Runtime Data Area에 있는 Method Area에 로드하는 순간부터 메모리를 할당 및 부여해 줍니다.
4. 바이트 코드 해석 및 실행 (Byte Code Interpretation and Runtime)
이 과정은 Runtime Data Area의 Method Area에 저장된. class 파일을 실행엔진의 Interpreter나 JIT(Just-in-Time Compiler)가 이 변환된 바이트코드를 해석하거나 기계어로 변환하여 실행합니다.
이때 JVM은 스택 기반의 가상머신으로 동작하여 스택 프레임을 사용하여 메서드 호출과 반환을 통해 스택 영역과 힙 영역에 저장됩니다.
이 과정에서
- Interpreter : 바이트 코드를 한 줄씩 순차적으로 해석하고 실행
- JIT : 바이트코드의 전체 블록을 기계어로 변환하여 실행
네이티브 코드에 대한 해석은 Native Metheod Library, Native Method Interface에서 수행합니다.
조금 더 자세히 들어가면 JIT 컴파일러는 프로그램 실행 중 자주 사용되는 부분(핫 스폿이라고도 합니다.)을 동적으로 식별하고, 그 부분만 기계어로 컴파일하여 성능을 향상시키는 역할을 합니다.
JIT 컴파일러의 흐름
1. 인터프리터 실행 : 프로그램 실행 시 인터프리터는 바이트 코드를 한 줄씩 읽어서 실행합니다. 이 과정은 느리지만, 프로그램의 어느 부분이 자주 실행되는 지를 알 수 있습니다.
2. 핫 스폿 식별 : 실행 도중에, 인터프리터는 일정 횟수 이상 실행되는 코드 블록(핫 스폿)을 식별합니다. 이는 프로그램의 성능에 중요한 부분이기 때문에 최적화의 대상이 됩니다.
3. JIT 컴파일 : 핫 스폿이 식별되면, JIT 컴파일러는 해당 바이트 코드를 기계어로 컴파일합니다. 이 과정은 일시적으로 시간이 소요되지만, 한 번 컴파일된 코드는 매우 빠르게 실행됩니다.
(컴파일 된 코드는 "코드 캐시", 또는 "JIT캐시" 라고 불리는 특별한 메모리 영역에 저장됩니다.)
4. 컴파일 된 코드 실행 : 이후 해당 핫 스폿이 다시 실행될 때, 인터프리터는 더 이상 바이트 코드를 해석하지 않고, 최적화된 기계어 코드를 캐싱하여 빠르게 실행할 수 있습니다.
➕ 클래스 프리로딩 또는 클래스 웜업 전략
일반적으로 JVM은 클래스를 필요로 할 때에만 로드하는 "지연 로딩" 방식을 사용합니다. 즉, 프로그램이 실행되어 해당 클래스의 코드가 실제로 필요한 순간에 클래스 로딩이 일어나게 됩니다. 반면에 클래스 프리로딩은 프로그램 실행 초기 단계에서 미리 사용자 정의 클래스와 자주 사용될 것으로 예상되는 자바 표준 라이브러리 클래스를 로드하는 기법입니다. 이렇게 하면, 프로그램 실행 중 클래스 로딩으로 인한 지연 시간을 줄일 수 있습니다.
5. 가비지 컬렉션(GC, Garbage Collection)
가비지 컬렉션은 JVM에서 더 이상 사용하지 않는 객체를 자동으로 감시하고 메모리에서 자동으로 해제하는 역할을 수행합니다. 이를 통해 메모리 관리를 최적화할 수 있습니다.
6. 예외 처리(Exception Handling)
예외처리는 프로그램 실행 도중 발생하는 예기치 않은 상황으로, 예외가 발생하면 JVM은 해당 예외를 적절히 처리하고 예외 상황에 대한 적절한 조치를 취합니다.
7. 프로그램 종료(End of Program)
프로그램 실행이 완료되거나 명시적으로 종료하면 JVM은 사용한 메모리를 반환하고 자원을 정리합니다.
다음 포스팅에서는 Java 메모리구조 (Runtime Data Area) 에 대해서 조금 더 상세하게 다뤄보겠습니다.
'CS > Java' 카테고리의 다른 글
[Java] 추상클래스와 인터페이스의 차이 (0) | 2024.04.19 |
---|---|
[Java] 오버로딩(Overloading)과 오버라이딩(Overriding) 차이 (0) | 2024.04.14 |
[Java] 제네릭이란?(Generic) (0) | 2024.04.04 |
[Java] Garbage Collection(GC) 이란? (0) | 2024.03.01 |
[Java] Java 메모리 영역 (0) | 2024.02.19 |