JIT 컴파일, JVM

whco·2021년 8월 5일
0

mostly from wikipedia JIT 컴파일

JIT 컴파일(just-in-time compilation) 또는 동적 번역(dynamic translation)은 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일 기법.

전통적인 입장에서 컴퓨터 프로그램을 만드는 방법은 두 가지가 있는데, 인터프리트 방식과 정적 컴파일 방식

  • 인터프리트 방식은 실행 중 프로그래밍 언어를 읽어가면서 해당 기능에 대응하는 기계어 코드를 실행
  • 정적 컴파일은 실행하기 전에 프로그램 코드를 기계어로 번역

    장단점이 뭘까?

    • 바이트코드나 소스코드를 최적화 과정이 없이 번역하기 때문에 성능이 낮다.
    • 정적으로 컴파일하는 언어(예시: c 언어)는 실행 전에 무조건 컴파일을 해야하기 때문에 다양한 플랫폼에 맞게 컴파일을 하려면 시간이 오래 걸린다

JIT 컴파일러는 두 가지의 방식을 혼합한 방식으로 생각할 수 있는데, 실행 시점에서 인터프리트 방식으로 기계어 코드를 생성하면서 그 코드를 캐싱(링크 걸 예정)하여, 같은 함수가 여러 번 불릴 때 매번 기계어 코드를 생성하는 것을 방지

자바 가상 머신(JVM)과 .NET, V8(node.js)에서는 JIT 컴파일을 지원

  • JVM : 자바 가상 머신(영어: Java Virtual Machine, JVM)은 자바 바이트코드를 실행할 수 있는 주체
    • 일반적으로 인터프리터나 JIT 컴파일 방식으로 다른 컴퓨터 위에서 바이트코드를 실행할 수 있도록 구현
    • 자바 바이트코드는 플랫폼에 독립적이며 모든 자바 가상 머신은 자바 가상 머신 규격에 정의된 대로 자바 바이트코드를 실행
    • 표준 자바 API까지 동일한 동작을 하도록 구현한 상태에서는 이론적으로 모든 자바 프로그램은 CPU나 운영 체제의 종류와 무관하게 동일하게 동작할 것을 보장
    • 포인터를 지원하되 C와 같이 주소 값을 임의로 조작이 가능한 포인터 연산이 불가능
    • 단일 상속 형태의 객체 지향 프로그래밍을 가상 머신 수준에서 구현
    • 명령어에서 스택에서 가져올 피연산자의 타입을 명령어에 지정(예: 정수 덧셈은 iadd, 단정밀도 실수 덧셈은 fadd)

자바 컴파일러가 자바 프로그램 코드를 바이트코드로 변환한 다음, 실제 바이트코드를 실행하는 시점에서 자바 가상 머신이 바이트코드를 JIT 컴파일을 통해 기계어로 변환

  • 바이트 코드 : 바이트코드(Bytecode, portable code, p-code)는 특정 하드웨어가 아닌 가상 컴퓨터에서 돌아가는 실행 프로그램을 위한 이진 표현법이다. 하드웨어가 아닌 소프트웨어에 의해 처리되기 때문에, 보통 기계어보다 더 추상적이다.
  • 의문 : JVM 만드는 것도 결국 운영체제 별로 다르게 만들어야 되는 것 아닌가??
    • C/C++ : 소스 코드 -> exe파일(기계어)(by Compiler) -> 실행(by OS)
    • Java : 소스 코드 -> class파일(bytecode)(by javac.exe) -> 실행(by JVM의 JIT 컴파일을 통해 기계어로 변환)
  • 의 과정에서 .c를 기계어로 만드는 과정이 OS에 따라 다르고, .java를 .class로 만드는 과정은 OS 독립적이지만, .class를 기계어로 만드는 과정은 OS에 따라 다를 것이다. 어차피 무슨 언어를 쓰든 한 번은 OS의존적인 제작해야 하는데 왜 느려지면서 굳이?
    • 내 생각엔 코딩할 때 함수를 쓰는 이유와 비슷. JVM 이라는 중간 툴을 한 번만 잘 만들어 놓으면 편리하고 안정적이어서겠지..? 시간 날 때 알아보기
      -> 플랫폼 별로 가상 머신을 개발하는 과정은 컴파일러를 만드는 것보다 간단
      1. 복잡한 최적화 과정은 바이트코드 컴파일러가 대신 해주므로 고려하지 않아도 된다.
      2. 바이트코드는 빠른 기계어 변환을 목적으로 설계되었기 때문에 일반적인 컴파일러보다 제작 과정이 수월하다.

이런 기계어 변환은 코드가 실행되는 과정에 실시간으로 일어나며(그래서 Just-In-Time이다), 전체 코드의 필요한 부분만 변환한다. 기계어로 변환된 코드는 캐시에 저장되기 때문에 재사용시 컴파일을 다시 할 필요가 없다.
동적 컴파일 환경은 실행 과정에서 컴파일을 할 수 있기 위해 만들어졌다.
JIT는 정적 컴파일러 만큼 빠르면서 인터프러터 언어의 빠른 응답속도를 추구하기 위해 사용.
바이트코드 컴파일러가 시간이 많이 소요되는 최적화를 미리 해주기 때문에 바이트코드에서 기계어 번역은 훨씬 빠르게 진행될 수 있다.


JIT 장점

  1. 컴파일이 cpu나 운영체제에 따라 다르게 진행될 수 있다. 예를 들어 cpu가 SSE2 vector instruction을 지원한다면 cpu는 이를 활용하는 방법으로 최적화를 진행한다.
  2. 정적 컴파일러 언어로 Garbage Collection을 지원하게 만들 수 있지만, JIT 시스템을 이용하면 더 쉽게 GC를 사용할 수 있다.

0개의 댓글