📝 정리
자바는 컴파일 언어가 아닌 하이브리드 언어이다
- 자바는 WORA 원칙을 유지하기 위해, 원시 코드를 컴파일하여
.class파일로 변환한다. - 해당 바이트코드를 JVM이 한 줄씩, 즉 인터프리터 방식으로 해석하면서 실행하게 된다.
- 하지만 인터프리터 방식으로만 실행하기에는 속도가 너무 느리다는 단점이 존재한다.
- 때문에
JIT 컴파일러가 개입하게 된다.
JIT 컴파일러
- JIT 컴파일러는 실행 중(Run TIme)에 일부 코드를 네이티브 코드로 변환하여 최적화시킨다.
- 모든 코드에 대해 변환하는 것은 아니며, 반복적으로 실행되는 코드(핫스팟)에 대해서 변환 후 캐싱한다.
-
컴파일 되어 캐싱한 네이티브 코드는, JVM의 메모리 내(JIT Code Cache 영역) 에 저장된다.
-
이는 프로그램이 실행되는 동안만 유지되며, 프로그램이 종료되면 사라진다. ⇒ 즉, 실행 속도는 거의 동일하다. 그러나 같은 코드더라도 JIT가 적용하는 최적화 방식과 타이밍이 달라질 수 있어 실행 속도가 완전히 같지 않을 수 있다.
-
- 모든 코드에 대해 변환하는 것은 아니며, 반복적으로 실행되는 코드(핫스팟)에 대해서 변환 후 캐싱한다.
“변환한 네이티브 코드는 프로그램이 종료되면 사라진다. JIT는 네이티브 코드를 디스크에 저장하지 않고 메모리에만 저장하기 때문인데, 왜 그럴까?”
- JIT는 실행 중에 성능을 분석하면서 최적화를 동적으로 조정할 수 있는데, 디스크에 네이티브 코드를 저장하게 되면 이러한 조정이 불가능해지기 때문이다.
- 예를 들어, 인라이닝 기법을 사용하다가 실행 도중에 사용을 중지할 수 있다.
- JIT는 반복적으로 호출되는 메서드에 대해서, 메서드 호출을 제거하고 메서드 내용을 직접 삽입하여 최적화 하는 인라이닝 기법을 사용한다.
public static int calculate(int x) {
return x * 2;
} int result = calculate(i); // 매번 메서드 호출 int result = i * 2; // 메서드 호출이 사라지고 직접 연산- 컴파일 과정은 맞으나, C/C++과 같은 전통적인 방식과 다르게 전체를 한 번에 변환하는 것이 아니라 실행 중 일부만 변환하기 때문에 이를 동적 컴파일(Dynamic Compliation) 이라고도 부른다.
public class JITExample {
public static void main(String[] args) {
System.out.println("Hello, Java!"); // ✅ 실행 1번 (JIT 대상 X)
for (int i = 0; i < 10000; i++) { // 🔥 핫스팟 (JIT 변환 O)
calculate(i);
}
printMessage(); // ✅ 실행 1번 (JIT 대상 X)
}
public static void calculate(int x) {
int result = x * 2;
}
public static void printMessage() {
System.out.println("This is a message!");
}
} “왜 모든 코드를 JIT으로 컴파일하지 않을까?”
-
메모리 사용 문제 - 모든 코드를 네이티브 코드로 변환하면 메모리 사용량이 증가한다. - 자바는 서버 환경에서도 사용되므로 메모리 관리가 중요하다.
-
컴파일 시간 오버헤드
- JIT 컴파일에는 시간이 걸린다.
- 사용되지 않는 코드를 굳이 네이티브 코드로 변환하면 불필요한 연산이 발생하기에, 실행 중 필요해지는 코드만 변환하는 게 효율적이다.
-
실행 방식의 유연성
- JIT의 동적 컴파일과 인터프리터의 빠른 첫 실행의 이점을 동시에 취할 수 있다.
⇒ 즉, JIT과 인터프리터가 공존하는 이유는 성능 최적화와 메모리 절약을 동시에 하기 위해서이다.
결론적으로, Java는 바이트코드를 실행할 때 인터프리터 방식과 JIT 컴파일러가 공존하는 하이브리드 언어이다.
💡 느낀 점 및 배운 점
-
이전부터 Python은 인터프리터, Java는 컴파일 언어라는 생각을 가지고 그렇게 배웠었는데, 자세히 파고드니 그렇지 않다는 것을 알게 되어 유익했다.
-
Java 파일이 컴파일 되고 해석되며 최종적으로 실행하는 일련의 과정을 알 수 있었다. 또한 JIT 컴파일러, 동적 컴파일에 대한 지식도 습득할 수 있었다.
-
.class파일을 한 번 까보면 재미있을 것 같다는 생각이 든다.