반응형
해당 글에서는 Java Application 환경에서 Java 소스코드가 JVM 내에서 수행되는 전반적인 과정에 대해서 확인해 봅니다.
1) JVM(Java Virtual Machine)
💡 JVM(Java Virtual Machine)
- 자바 프로그램을 실행하기 위한 가상 머신입니다. 이를 통해 자바 언어로 작성된 프로그램을 특정 운영 체제에 종속되지 않고 실행할 수 있게 해 줍니다.
2) JVM 동작 과정
💡 해당 동작과정은 JVM에서 자바 프로그램을 효율적으로 실행하기 위해 컴파일 수행 -> 클래스 로딩 -> 메모리 할당 -> 바이트 코드 해석 및 실행 -> 가비지 컬렉션 -> 예외 처리 -> 프로그램 종료 과정을 수행합니다.
1. 컴파일(Compile)
💡 컴파일 (Compile)
- 자바 프로그램을 실행시키는 시점에 자바 소스 코드(.java)를 컴파일러(javac)를 통해 바이트 코드(.class)로 변환을 수행합니다.
- 이 변환된 바이트코드는 플랫폼에 대해 독립적이며 JVM이 실행할 수 있는 언어로 변환을 합니다.
- 해당 과정은 Java Source File(java) → (Java Complier) → Java Byte Code(class)에서 수행합니다.
2. 클래스 로딩(Class Loading)
💡 클래스 로딩(Class Loading)
- 해당 과정은 JVM에 컴파일된 바이트 코드를 읽고 메모리에 로드를 수행합니다.
- 해당 메모리가 로드되는 시점은 ‘파일을 실행(Runtime)’ 할 때이며 ‘Runtime Data Area’로 로딩을 시킵니다.
- 해당 과정은 Java Byte Code(class) → Class Loader에서 수행합니다.
[ 더 알아보기 ]
💡 메모리를 로딩시킨다는 말은 무슨 말인가?
- JVM이 자바 프로그램을 실행하기 위해 필요한 클래스와 객체들을 메모리에 옮기는 과정을 말합니다. 이를 통해 자바 프로그램이 실행될 때 필요한 데이터와 코드가 메모리에 준비되어 실행될 수 있게 됩니다.
3. 메모리 할당(Memory Allocation)
💡 메모리 할당(Memory Allocation)
- 해당 과정은 메모리에 로딩되어 온 데이터나 코드들에 대해 ‘Runtime Data Area’에 크기에 맞게 메모리를 할당 및 부여하는 것을 수행합니다.
- 메모리 할당은 주로 힙 영영에 객체나 배열이 생성될 때 객체의 크기에 맞게 힙 영역에 메모리를 할당합니다.
- 해당 과정은 Class Loader → Runtime Data Area에서 수행합니다.
4. 바이트 코드 해석 및 실행(Byte Code Interpretation and Runtime)
💡 바이트 코드 해석 및 실행(Byte Code Interpretation and Runtime)
- 해당 과정은 JVM의 클래스 파일의 ‘바이트 코드를 해석’하여 명령어를 수행하는 역할을 수행합니다.
- 해당 역할을 Execution Engine의 Interpreter와 JIT가 수행을 하며 네이티브 코드에 대한 해석은 Native Method Interface, Native Method Libaray에서 수행을 합니다.
- 이때 JVM은 스택 기반의 가상머신으로 동작하여 스택 프레임을 사용하여 메서드 호출과 반환을 관리합니다.
- JVM 내에서 Runtime Data Area와 Execution Engine(JIT, Interpreter)에서 수행을 합니다.
4.1. 인터프리터(Interpreter)의 바이트 코드 수행 및 실행 과정
💡 인터프리터(Interpreter)
- Java 프로그램을 실행하기 위해 바이트 코드를 한 줄씩 해석하는 도구입니다. 이를 통해 Java 소스 코드를 컴파일하여 생성된 바이트 코드를 실행할 수 있습니다.
💡 인터프리터 (Interpreter) 수행과정
1. 이전에 생성하고 할당된 메모리를 기반으로 바이트 코드를 읽어옵니다.
2. 인터프리터를 통해 바이트 코드를 한 줄씩 읽고 해석합니다.
3. 바이트 코드를 해석하는 동안 인터프리터는 필요한 메모리 및 리소스를 할당하고 해당 바이트 코드에 따라 실행합니다.
4. 바이트 코드가 실행되는 동안 인터프리터는 필요한 경우에 따라 라이브러리 및 다른 클래스를 로드하고 사용합니다.
5. 인터프리터는 바이트 코드를 순차적으로 해석하면서 프로그램을 실행합니다.
4.2. JIT(Just-In-Time)의 바이트 코드 수행 및 실행 과정
💡 JIT(Just-In-Time)
- Java 프로그램을 실행하고 실행 패턴을 분석하고 최적화하는 동적 컴파일 기술입니다.
- 해당 기술은 프로그램을 실행하는 동안 실시간으로 바이트 코드를 기계어로 변환하여 성능을 향상합니다.
- 코드를 인터프리터 방식으로 실행하는 것보다 더 빠른 실행 속도를 제공할 수 있습니다.
💡 JIT(Just-In-Time) 수행과정
1. 이전에 생성하고 할당된 메모리를 기반으로 바이트 코드를 읽어옵니다.
2. JIT 컴파일러는 실행 중인 프로그램을 모니터링하면서 빈번하게 실행되는 코드 블록을 식별합니다.
3. 해당 코드 블록은 인터프리터에 의해 실행될 때마다 JIT 컴파일러에 의해 기계어로 변환됩니다.
4. JIT 컴파일러는 변환된 기계어 코드를 캐시에 저장합니다.
5. 이후 동일한 코드 블록이 다시 호출되면, 캐시에 저장된 기계어 코드를 실행하여 인터프리터에 비해 훨씬 빠른 실행 속도를 제공합니다.
[더 알아보기 ]
💡 컴파일러(Compiler)
- 소스 코드를 기계어 또는 바이트 코드로 변환하는 프로그램으로 일반적으로 고급언어로 작성된 소스코드를 기계어로 변환하여 실행할 수 있는 형태로 만들어주는 역할을 수행합니다.
4.3. Native Method Interface의 바이트 코드 수행 과정
💡 Native Method Interface (JNI)
- Java 프로그램이 C 또는 C++과 같은 네이티브 코드를 호출하고 상호 작용할 수 있게 해주는 기능을 제공합니다.
- 해당 부분은 JVM이 바이트 코드를 해석하고 실행하는 동안 네이티브 메서드를 호출하고 해당 코드가 네이티브 코드로 실행될 수 있도록 합니다.
4.4. Native Method Libaray의 바이트 코드 수행
💡 Native Method Library
- C 또는 C++과 같은 특정 프로그래밍 언어로 구현된 네이티브 메서드의 컬렉션입니다. 추가 기능이나 시스템 수준의 리소스에 액세스 할 수 있는 기능을 제공합니다.
- 해당 부분은 JVM이 바이트 코드를 해석하는 동안 호출되고 실행됩니다.
5. 가비지 컬렉션(GC, Garbage Collection)
💡 가비지 컬렉션(GC, Garbage Collection)
- JVM에서 더 이상 사용되지 않은 객체를 자동으로 감시하고 메모리에서 자동으로 해제하는 역할을 수행합니다. 이를 통해 메모리 관리를 최적화할 수 있습니다.
- JVM 내에서 Execution Engine(Garbage Collection)에서 수행을 합니다.
💡 가비지 컬렉션의 동작 과정
1. Marking (표시): 가비지 컬렉터는 모든 객체를 스캔하고 참조되는 객체들을 표시합니다. 이 과정에서 도달 가능한 객체들은 표시됩니다.
2. Sweeping (정리): 가비지 컬렉터는 표시되지 않은 객체들을 메모리에서 제거합니다. 이러한 객체들은 도달할 수 없는 객체로 간주되며 가비지로 처리됩니다.
3. Compacting (압축): 가비지 컬렉터는 메모리에서 제거된 객체들로 인해 생긴 빈 공간을 모아서 압축합니다. 이렇게 함으로써 메모리의 단편화를 최소화하고, 연속된 메모리 공간을 확보합니다.
6. 예외 처리(Exception Handling)
💡 예외 처리(Exception Handling)
- 예외처리는 프로그램 실행 도중 발생하는 예기치 않은 상황으로, 예외가 발생하면 JVM은 해당 예외를 적절히 처리하고 예외 상황에 대한 적절한 조치를 취합니다.
- JVM은 예외 처리를 위해 예외 핸들러를 사용하며, 예외가 발생했을 때 해당 예외를 처리할 수 있는 예외 핸들러를 찾아 처리합니다.
💡 JVM 예외 처리 과정
1. 예외 발생: 프로그램이 실행 중에 예외가 발생합니다. 이는 예상치 못한 상황 또는 오류가 발생한 것을 의미합니다.
2. 예외 객체 생성: 예외가 발생하면 JVM은 해당 예외를 나타내는 예외 객체를 생성합니다. 이 객체는 예외의 유형, 메시지 및 예외가 발생한 위치 정보를 포함합니다.
3. 예외 처리: JVM은 예외를 적절히 처리하기 위해 예외 처리기(Exception Handler)를 찾습니다. 예외 처리기는 예외를 처리하는 코드 블록으로, 예외를 처리하는 방법을 정의합니다.
4. 예외 전파: 예외 처리기가 발견되지 않거나 처리하지 못한 경우, 예외는 현재 실행 중인 메서드에서 호출한 메서드로 전파됩니다. 이 과정은 메소드 호출 스택을 따라 위로 올라갑니다.
5. 예외 처리기 찾기: 예외는 예외를 전파한 메서드의 호출자에게 전달됩니다. JVM은 호출자 메서드에서 예외 처리기를 찾습니다. 이 과정은 호출자 메서드의 호출자로 계속해서 진행됩니다.
6. 예외 처리: 예외 처리기가 발견되면 예외 처리기의 코드 블록이 실행됩니다. 예외 처리기는 예외를 처리하거나 예외를 다시 던지는 등의 작업을 수행할 수 있습니다.
7. 예외 체인: 예외 처리기가 예외를 다시 던지는 경우, 예외는 다시 호출자로 전파되며, 이 과정은 호출자 메소드의 호출자로 계속해서 진행됩니다. 이렇게 예외가 여러 단계로 전파되는 구조를 예외 체인(Exception Chaining)이라고 합니다.
7. 프로그램 종료(End of Program)
💡 프로그램 종료(End of Program)
- 프로그램 실행이 완료되거나 명시적으로 종료되면 JVM은 사용한 메모리를 반환하고 자원을 정리합니다.
💡 프로그램 종료 과정
1. 정리 작업: 프로그램이 종료되기 전에 필요한 정리 작업을 수행합니다. 이는 열려 있는 파일을 닫고, 할당된 리소스를 해제하는 등의 작업을 포함할 수 있습니다.
2. 종료 코드 반환: 프로그램이 완전히 종료되었을 때, 종료 코드를 반환합니다. 종료 코드는 프로그램이 성공적으로 종료되었는지 또는 오류로 종료되었는지를 나타내는 값입니다.
3. 자원 해제: 프로그램이 사용한 모든 자원을 해제합니다. 이는 할당된 메모리의 해제, 열려 있는 연결의 닫힘 등을 포함할 수 있습니다.
💡 다음 글에서는 Runtime Data Area에 대해서 상세히 알아봅니다.
오늘도 감사합니다. 😀
반응형
'Java > 이론 및 문법' 카테고리의 다른 글
[Java] JVM(Java Virtual Machine) 이해하기 -3 : 가비지 컬렉터(GC, Garbage Collector) (0) | 2023.10.09 |
---|---|
[Java] JVM(Java Virtual Machine) 이해하기 -2 : 메모리 영역(Runtime Data Area) (0) | 2023.10.07 |
[Java] 반복문의 제어문(Control Flow Statement) 이해하기 (0) | 2023.10.03 |
[Java] 사용 목적에 따른 반복문(Loop) 이해하기 (0) | 2023.08.27 |
[Java] 다양한 형 변환(Type Conversion) 방법 이해하기 : 캐스팅(Casting) (0) | 2023.08.26 |