Class Loader
: 컴파일된 바이트 코드를Runtime Data Area
에 로드
Execution Engine
은 이 바이트 코드를 실행
Execution Engine
은 이 바이트 코드를 기계어로 변환하여 실행
Execution Engine
은 바이트 코드를 기계어로 변하는 과정에서 2가지 방법을 사용합니다.
Interpreter
: 바이트 코드를 한 줄씩 읽어서 실행JIT(Just-In-Time) Compiler
: 바이트 코드의 실행 빈도를 분석하여, 자주 사용되는 코드를 더 효율적으로 기계어로 변환1.2
의 단점을 보완하기 위해, Interpreter
로 바이트 코드를 수행하다가 적절한 시점(임계치)이 오면, 바이트 코드 전체를 컴파일하여 네이티브 코드로 변환한다.또한 Execution Engine
은 Runtime Data Area
의 Heap 메모리 관리를 위해 Garbage Collector
를 포함하고 있어, 사용하지 않는 메모리 자원을 자동으로 회수하여 메모리를 효율적으로 관리합니다.
JIT Compiler의 동작
void jitCompilerTest() {
int a = 0;
for (int i = 0; i < 500; i++) {
long startTime = System.nanoTime();
for (int j = 0; j < 10000; j++)
a++;
long endTime = System.nanoTime();
System.out.printf("%d\t%d\n", i, endTime - startTime);
}
}
해당 코드는 메서드가 수행될 때 시간을 측정하는데, 상위 for문이 실행될 때마다 내부에서 a에 1을 더하는 연산을 10,000번 수행하고, 소요되는 시간을 출력합니다.
실행 결과는 다음과 같습니다.
// 0~10의 결과
0 103900
1 126000
2 124800
3 124600
4 110100
5 108500
6 118600
7 111900
8 96200
9 18900
10 11700
// 76~499의 결과
76 24000
77 11400
78 11400
79 56800
80 600
81 0
82 100
83 100
84 0
85 100
86 100
...
495 0
496 100
497 0
498 0
499 100
JIT Compiler
는 인터프리터의 같은 메서드가 수행되더라도 새로 해석하여 수행한다는 단점을 보완하기 위해서 나왔다고 설명했었습니다.
결과를 통해 확인해보니, 시간이 점차 줄어들더니 80번째부터는 연산 시간이 매우 단축되었습니다.
시간 단축의 과정은 아래와 같습니다.
초기 실행은 인터프리터가 바이트 코드를 한 줄씩 읽어서 실행
합니다. 이 때 각 바이트 코드의 실행 횟수 등을 분석합니다. 바이트 코드의 실행 빈도 등을 기반으로 컴파일 임계치를 설정
합니다. 임계치는 메서드 호출 횟수
또는 반복문 수행 빈도
등으로 결정될 수 있습니다.임계치에 도달한 바이트 코드는 JIT Compiler에 의해 네이티브 코드(기계어)로 변환
됩니다.이렇게 변환된 네이티브 코드는 인터프리터를 거치지 않고 직접 실행하기 때문에 속도가 크게 향상되는 것을 결과로 확인할 수 있습니다.
JIT Compiler
는 Java 벤더에 따라 구현되어 있는 방법은 다르지만JIT Compiler
의 명세에 따라 각 Java의 벤더가 구현되어야 합니다.
가비지 컬렉션은 프로그래머가 직접적으로 메모리를 할당하고 해제하는 것 대신,
프로그램 실행 중에 더 이상 필요하지 않은 메모리를 자동으로 식별하고 해제
합니다.
Heap
영역에서 동적으로 할당했던 메모리 중 필요 없게 된 메모리 객체(garbage)를 모아 주기적으로 제거
이를 통해
를 하도록 할 수 있습니다.
따라서 가비지 컬렉션은 프로그램이 실행되는 동안 발생하는 쓸모 없어진 메모리를 효율적으로 관리
하여 프로그램의 성능과 안정성을 향상시키는 데 도움을 줍니다.
Java에서는 가비지 컬렉터를 이용해 Java 프로세스는 한정된 메모리를 효율적으로 사용
할 수 있고, 개발자 입장에서는 메모리 관리, 메모리 누수(Memory Leak) 문제에서 대해 관리하지 않아도 되서 개발에만 집중할 수 있습니다.
좀 더 자세한 내용은 Garbage Collection에 포스팅 하였으며, JVM
은 아래 전제 조건의 2가지를 따르면서 Mark and Sweep
방식을 따릅니다.
약한 세대 가설(Weak Generational Hyphothesis)
Unreachable
상태가 된다.참고 자료
https://www.javatpoint.com/java-interpreter
https://docs.oracle.com/javase/specs/jvms/se17/html/
https://medium.com/@gsy4568/jvm%EC%9D%98-%EB%8F%99%EC%9E%91%EC%9D%80-execution-engine-ed2480176a15