1. 소스 코드를 실행하기
개발자는 java로 코드를 작성한 후 ide 상단에 Run이라는 버튼을 눌러서 실행 결과를 확인한다.
내부에서 어떤 과정이 일어나길래 이게 가능할까? 이를 알기 위해서는 JVM에 대해 알아야 한다.
2. JVM이란?
JVM(Java Virtual Machine)이란 자바의 바이트 코드를 실행할 수 있는 가상의 머신, 컴퓨터다.
JVM은 CPU나 운영체제와 무관하게 자바로 작성된 코드를 실행시킬 수 있기 때문에 '플랫폼에 독립적으로 동작한다'라고 할 수 있다.
JVM은 여러 구성 요소로 이루어져 있다
- 클래스 로더(Class Loader) : 클래스 파일을 런타임 데이터 영역으로 로드하는 역할.
- 실행 엔진(Execution Engine) : 바이트 코드를 해석하고 실행.
- 런타임 데이터 영역(Runtime Data Area) : 프로그램 실행 중에 사용되는 메모리 영역. 위 사진의 JVM Memory
- 네이티브 인터페이스(Native Method Interface) : 자바 프로그램, 운영 체제, 하드웨어 리소스 간의 상호작용을 도움
- 가비지 컬렉션(Garbage Collection) : 실행 엔진에 포함되어 있으며 사용하지 않는 객체 회수를 통해 메모리를 관리
3. JVM의 동작 과정 요약
메모장에 간단하게 그려봤다. 자세한 내용은 바로 다음에 설명한다.
4. JVM이 프로그램을 실행하는 과정
- 작성된 소스코드를 JDK안에 있는 컴파일러가 바이트 코드로 변환한다.
- .java파일을 .class로 변환하는 과정이다.
- 바이트 코드를 클래스 로더가 가져온다.
- 클래스 로더가 프로그램의 실행에 필요한 클래스 파일을 런타임 데이터 영역, 즉 메모리에 로드한다.
- 클래스 로더가 바이트 코드를 검증 및 초기화를 한다.
- 검증 단계에서 잘못된 코드나 악성 코드가 발견되면 예외를 발생시킨다.
- 검증 후, 클래스의 정적 변수를 메서드에 할당하고 초기화 한다.
- 실행 엔진이 main() 메서드를 찾으며 프로그램의 진입점으로 사용한다.
- 실행 엔진의 인터프리터 or JIT 컴파일러가 바이트코드를 해석하고 실행한다.
- 인터프리터는 자바 바이트코드를 한 줄씩 기계어로 번역하며 실행한다. 바이트 코드를 빠르게 실행할 수 있지만 반복적으로 호출되는 메서드를 매번 해석하기 때문에 비효율 적이며 실행 속도가 느릴 수 있다.
- JIT 컴파일러는 자주 호출되는 자바 바이트코드를 기계어로 변환하여 최적화한다. 일부분을 미리 컴파일 했기 때문에 캐시처럼 이용해서 실행 성능이 향상되지만, 그만큼 컴파일에 시간이 소요된다.
- 실행 엔진에 포함된 가비지 컬렉션(GC)이 힙(Heap) 메모리 영역에서 사용되지 않는 객체의 메모리를 회수한다.
- 가비지 컬렉션은 자동으로 수행되기 때문에 프로그래머가 메모리 관리를 할 필요를 없도록 만들어준다.
- main()메서드가 완료되면 JVM은 프로그램을 종료하고 할당한 자원을 해제하며 이 과정에서 가비지 컬렉션이 프로그램이 차지한 메모리를 정리한다.
5. 왜 알아야 할까?
JVM의 동작 원리를 이해하는 것은 여러가지 이유로 중요하다.
JVM을 잘 이해한다면 프로그램의 메모리 관리를 더 깊게 고민할 수 있기 때문에 성능 최적화와 실행 중에 발생할 수 있는 문제의 해결 능력을 높일 수 있다.
따라서 결과적으로 프로그래밍 능력에 중요하다고 볼 수있다.
JVM의 전체적인 동작 흐름에 대해 공부해봤는데 JVM의 메모리 구성과 가비지 컬렉션의 자동 메모리 관리 과정에 대해 더 알아봐야겠다.