문제

JIT 컴파일러와 CLR의 차이점은 무엇입니까? 코드를 IL에 컴파일하고 CLR이 해당 코드를 실행하면 JIT가 무엇을하고 있습니까? CLR에 제네릭을 추가하면 JIT 컴파일이 어떻게 변경 되었습니까?

도움이 되었습니까?

해결책

JIT는 CLR의 한 측면입니다.

특히 원래 언어 컴파일러 (예 : Microsoft C#의 CSC.Exe)가 현재 프로세서 (및 현재 프로세스에서 노출되는 아키텍처)로 제작 한 CIL/MSIL (이하 IL이라고 함)을 변경하는 데 책임이있는 부분입니다. , 예를 들어 32/64 비트). 문제의 어셈블리가 ngen'd 인 경우 JIT 프로세스는 완전히 불필요하고 CLR은이 코드를 제대로 실행하지 않습니다.

중간 표현에서 아직 변환되지 않은 방법이 사용되기 전에이를 변환하는 것은 JIT의 책임입니다.
정확히 언제 JIT가 시작될 것입니다. 구현은 구현되며 변경 될 수 있습니다. 그러나 CLR 디자인은 JIT가 발생하도록 의무화합니다 ~ 전에 관련 코드는 실행되며, 대조적으로 JVM은 한동안 코드를 해석 할 수 있으며 별도의 스레드는 기계 코드 표현을 만듭니다.
'정상'CLR은 a를 사용합니다 사전 제트 스터브 접근 방법별로 JIT가 사용되는 경우에만 편집됩니다. 여기에는 초기 기본 메소드 스텁이 JIT에 메소드를 컴파일하도록 지시 한 다음 원래 호출을 수정하여 초기 스텁을 건너 뛰도록 지시하는 간접입니다. 현재 컴팩트 판은 대신로드 될 때 유형에서 모든 메소드를 컴파일합니다.

제네릭의 추가를 해결하기 위해.

이것은 내부 구현 세부 사항과 달리 Semantics의 관점에서 IL 사양에 대한 마지막 주요 변화였습니다.

몇 가지 새로운 IL 지침이 추가되었으며 계측 유형 및 멤버에는 더 많은 메타 데이터 옵션이 제공되었습니다. IL 레벨에서도 제약 조건이 추가되었습니다.

JIT가 일반 인수 (포함 된 클래스를 통해 명시 적 또는 암시 적으로)가있는 메소드를 컴파일하면 사용 된 각 유형에 대해 다른 코드 경로 (기계 코드 지침)를 설정할 수 있습니다. 실제로 JIT는 모든 참조 유형에 대해 공유 구현을 사용합니다. 변수는 동일한 의미를 나타내고 동일한 공간 (intptr.size)을 차지하기 때문입니다.

각 값 유형은 스택 / 힙의 변수의 감소 / 증가를 다루는 특정 코드가 생성됩니다. 또한 메소드를 호출하기 전에 구속 된 opcode를 방출함으로써 비 참조 유형의 많은 호출은 상자를 호출 할 필요가 없습니다 (이 최적화는 비 일반적인 경우에도 사용됩니다). 이것은 또한 기본값을 허용합니다<T> 올바르게 처리하고 널과 비교할 수있는 동작은 널리 널 값 유형을 사용 할 때 OPS (항상 거짓)로 제거되도록합니다.

반사를 통해 일반 유형의 인스턴스를 생성하기 위해 런타임에 시도 된 경우 런타임으로 유형 매개 변수를 검증하여 제약 조건을 전달합니다. 이것은 유형 시스템 내에서 사용되지 않는 한 JIT에 직접 영향을 미치지 않습니다 (가능하지는 않지만).

다른 팁

런타임 중에 실행되고 기계 코드에 컴파일되는 IL에 코드를 컴파일합니다. 이것이 JIT라고합니다.

편집하다, 더 많은 대답을 더 살펴보기 위해 (여전히 지나치게 단순화) :

Visual Studio에서 C# 코드를 컴파일하면 CLR이 이해하는 IL로 전환됩니다. IL은 CLR 위에서 실행되는 모든 언어에 대해 동일합니다 (.NET 런타임이 여러 언어를 사용하고 Inter-OP를 사용할 수 있습니다. 그들 사이에서 쉽게).

런타임 동안 IL은 기계 코드 (아키텍처에 따라 다름)로 해석 한 다음 실행됩니다. 이 프로세스는 단지 시간 컴파일 또는 JIT에서 짧게 호출됩니다. 필요한 IL 만 기계 코드로 변환됩니다 (그리고 한 번만 MachineCode로 컴파일되면 "캐시", 제 시간에 실행되기 전에 JIT라는 이름입니다.

이것이 C#의 모습입니다.

C# 코드 > C# 컴파일러 >> .NET 런타임 > JIT 컴파일러 > machinecode > 실행

그리고 이것이 VB의 모습입니다

VB 코드 > VB 컴파일러 >> .NET 런타임 > JIT 컴파일러 > machinecode > 실행

그리고 두 개의 첫 단계 만 볼 수 있듯이 각 언어마다 고유하며 IL로 바뀌면 모든 것이 동일합니다. 이전에 말했듯이 .NET 위에서 여러 다른 언어를 실행할 수있는 이유는 동일합니다.

Jon Skeet이 말했듯이 JIT는 CLR의 일부입니다. 기본적으로 이것은 후드 아래에서 일어나는 일입니다.

  1. 소스 코드는 공통 중간 언어 (CIL)로 알려진 바이트 코드로 컴파일됩니다.
  2. 모든 클래스의 메타 데이터와 모든 방법 (및 다른 모든 방법 : O)은 결과 실행 파일의 PE 헤더 (DLL 또는 EXE)에 포함됩니다.
  3. 실행 파일을 생성하는 경우 PE 헤더에는 실행 파일을 실행할 때 CLR (Common Language Runtime)을로드하는 기존 Bootstrapper도 포함되어 있습니다.

이제 실행할 때 :

  1. 부트 스트레이퍼는 CLR을 초기화하고 (주로 MSCorlib 어셈블리를로드하여) 어셈블리를 실행하도록 지시합니다.
  2. CLR이 메인 항목을 실행합니다.
  3. 이제 클래스에는 메소드 함수의 주소를 보유하는 벡터 테이블이있어 MyMethod를 호출하면이 테이블이 검색되고 주소에 대한 해당 호출이 이루어집니다. 시작시 모든 테이블의 모든 항목에는 JIT 컴파일러의 주소가 있습니다.
  4. 그러한 방법 중 하나에 대한 호출이 이루어지면, JIT는 실제 방법 대신 호출되고 제어됩니다. 그런 다음 JIT는 적절한 아키텍처를 위해 CIL 코드를 실제 어셈블리 코드로 컴파일합니다.
  5. 코드가 컴파일되면 JIT가 메소드 벡터 테이블로 들어갑니다. 주소를 컴파일 된 코드 중 하나로 바꾸어 모든 후속 호출이 더 이상 JIT를 호출하지 않도록합니다.
  6. 마지막으로 JIT는 실행을 컴파일 된 코드로 처리합니다.
  7. 아직 컴파일되지 않은 다른 방법을 호출하면 4로 돌아갑니다 ... 등 ...

JIT는 기본적으로입니다 부분 CLR의. 쓰레기 수집가는 또 다른 것입니다. 당신이 interop 책임 등을 넣는 곳은 또 다른 문제이며, 다른 하나는 내가 언급하기 위해 크게 자격이없는 곳입니다 :)

나는 실이 꽤 오래되었다는 것을 알고 있지만, 나는 내가 JIT를 이해하게하는 그림에 넣을 것이라고 생각했다. 훌륭한 책에서 나온 것입니다 Jeffrey Ritcher의 C#을 통해 CLR. 그림에서 그가 말하는 메타 데이터는 어셈블리의 유형에 대한 모든 정보가 저장되는 어셈블리 헤더에서 방출 된 메타 데이터입니다.

JIT image from CLR via C#

1) .NET 프로그램을 컴파일하는 동안 .NET 프로그램 코드는 중간 언어 (IL) 코드로 변환됩니다.

2) 프로그램을 실행할 때 중간 언어 코드는 방법이 호출 될 때와 같이 운영 체제 기본 코드로 변환됩니다. 이것을 JIT (정시) 컴파일이라고합니다.

  1. CLR (Common Language Runtime)은 통역사이며 제 시간 (JIT)은 .NET Framework의 컴파일러입니다.

2. JIT는 CLR에서 Microsoft 중간 코드 언어 (MSICL) 코드를 가져 와서 시스템 특정 명령어로 실행하는 .NET의 내부 컴파일러이며 CLR은 엔진으로 작동하는 반면 주요 작업은 코드가 CODE에 MSICL 코드를 제공하는 것입니다. 기계 사양에 따라 완전히 컴파일됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top