컴퓨터 구조를 공부하다가 컴파일 언어와 인터프리터 언어의 차이에 대해서 공부하는 도중 자바는 컴파일 언어이지만 인터프리터 언어적 특징도 가지고 있다는 글을 봤던 기억이 있어서 다시 찾아보았다. 찾던 도중 정리가 잘된 블로그를 발견해서 정리해보려고 한다.
컴파일 언어 vs 인터프리터 언어
- 모든 고급언어는 실행을 위해 machine native code로 변환된다.
- 컴파일 언어는 machine native code로 한번에 변환되는 과정을 통해 인터프리터 언어에 비해서 빠르고 효율적이다.
- 인터프리터 언어는 소스코드를 한줄씩 machine native code로 변환해서 실행하기 때문에 매우 느리다.
- 하지만 JIT(Just In Time) 컴파일 방식의 등장으로 인터프리터를 사용해도 괜찮을 정도로 격차가 크게 줄었다. 또한 인터프리터 언어는 런타임에 여러 플랫폼 위에서 최적화 될 수 있다.
- 자바와 JVM은 오늘날 대부분의 인기 플랫폼에서 동작하지만 자바 소스코드는 다른 컴파일 언어들과 마찬가지로 JVM에서만 동작하는 특별한 언어인 바이트코드로 변환된다.
바이트 코드는 기계어가 아니다. JVM은 런타임에 바이트코드를 기계어로 바꾸어 실행한다.
그래서 자바는 어떤 언어의 특징을 갖고 있는가
- 즉 자바를 지원하기 위해 각 플랫폼에 맞춰 변형되는 건 JVM이지 우리의 프로그램이나 라이브러리가 아니다.
- 현대의 JVM은 코드를 런타임에 최적화하여 컴파일 언어와 같은 성능을 가질 수 있도록 JIT 컴파일러 역시 지원한다.
- 자바 컴파일은 소스코드를 어떤 플랫폼에서도 동작할 수 있는 바이트코드를 포함한 java class file로 컴파일한다.
- JVM의 구성요소중 Exectuion Engine은 바이트 코드를 읽고 기계어로 변환하고 실행하는 역할을 한다.
JIT 컴파일러
- JIT 컴파일러는 전체 메서드의 바이트코드를 기계어로 컴파일한다. 그리고 컴파일한 메서드가 호출될때마다 사용할 수 있도록 한다.
- 하지만 자주 사용되지 않는 메서드까지 컴파일해서 메모리에 들고 있을 필요가 없기 때문에 Profiler라는 JIT 컴파일러의 특별한 컴포넌트가 런타임 동안 수집한 정보를 통해 핫스팟을 찾는 역할을 한다.
JVM은 핫스팟을 통해 어떤 코드를 JIT Compile 할지 결정한다.
- n번째 피보나치 수를 구하는 코드에서 JIT 컴파일러를 사용한 방식은 사용하지 않은 방식에 비해 5배 이상 빠른 속도를 보여주었다.
자바는 JIT 컴파일러를 통해 컴파일언어와 인터프리터 언어의 장점을 모두 가질 수 있게 되었다
- 최근 대부분의 인기있는 JVM은 JIT컴파일러와 인터프리터를 동시에 활용하여 성능과 플랫폼 중립적 실행을 가능하게 했다.
참고:
Is Java a Compiled or Interpreted Language? | Baeldung