ジャストインタイム(JIT)コンパイラーは何をしますか?


528

非JITコンパイラーとは対照的に、JITコンパイラーは具体的に何をしますか?誰かが簡潔で理解しやすい説明を与えることができますか?




2
youtube.com/watch?v=yQ27DjKnxwoが便利だと思いました。
Adam Zerner 2017年

回答:


518

JITコンパイラーは、プログラムの開始に実行さ、コード(通常はバイトコードまたはある種のVM命令)をその場で(または呼び出されるとジャストインタイムで)通常より高速な形式(通常はホストCPUのネイティブ)にコンパイルします。指図書。JITは動的ランタイム情報にアクセスできますが、標準コンパイラーはそうではなく、頻繁に使用される関数のインライン化などの最適化を行うことができます。

これは、プログラムが最初に実行される前にすべてのコードを機械語コンパイルする従来のコンパイラーとは対照的です。

言い換えれば、従来のコンパイラーは、初めて実行する前に、プログラム全体をEXEファイルとしてビルドします。新しいスタイルのプログラムの場合、アセンブリは疑似コード(pコード)で生成されます。OSでプログラムを実行した後(アイコンをダブルクリックするなど)にのみ、(JIT)コンパイラが起動し、Intelベースのプロセッサなどが理解できるマシンコード(Mコード)を生成します。


16
インタプリタされたコードとは対照的に、バイトコードまたはVM命令の実行はすぐに開始されますが、命令はマシン言語よりも遅く実行されます。
アーロン

3
JITは多くの場合、インタープリターコードと共に使用して機械語に変換しますが、はい、純粋にインタープリターされたコード(JITなし)は低速です。JITterのないJavaバイトコードでさえ、本当に遅いです。
マーク・シダイデ

48
ただし、ターゲットはマシンコードである必要はありません。JRubyには、いくつかの呼び出しの後にRubyソースコードをJavaバイトコードにコンパイルするJITコンパイラーがあります。次に、別の数回の呼​​び出しの後、JVM JITコンパイラーが起動し、バイトコードをネイティブコードにコンパイルします。
イェルクWミッターク

4
ヨルクが示唆したように、JITがすぐに呼び出されるとは限らないことに注意してください。多くの場合、コードは、JITする価値があると判断されるまで解釈されます。JITtingは遅延を引き起こす可能性があるため、まれに使用されるコードはJIT しない方が速く、したがって、全体的なランタイムよりも速い応答が重要です。
アダムJaskiewicz 2009

3
@ErikReppen:新しいマシンが出てきた場合、従来のコンパイラを使用してその新しいマシン用にプログラムをコンパイルおよび最適化すると、JITよりも速く結果が得られる可能性があります。一方、その新しいマシン用に最適化されたJITは、その新しいマシンが発明される前に公開されたコードのパフォーマンスを最適化できるようになります。
スーパーキャット2013

255

当初、コンパイラーは高水準言語(アセンブラーよりも高いレベルとして定義)をオブジェクトコード(マシンインストラクション)に変換し、それを(リンカーによって)実行可能ファイルにリンクしていました。

言語の進化のある時点で、コンパイラーは高水準言語を疑似コードにコンパイルし、それを(インタープリターによって)解釈してプログラムを実行します。これにより、オブジェクトコードと実行可能ファイルが削除され、これらの言語を複数のオペレーティングシステムとハードウェアプラットフォームに移植できるようになりました。Pascal(P-Codeにコンパイルされた)は最初の1つでした。JavaとC#は最近の例です。結局のところ、疑似操作のほとんどがバイト長であるため、Pコードという用語はバイトコードに置き換えられました。

Just-In-Time(JIT)コンパイラーは、ランタイムインタープリターの機能であり、メソッドが呼び出されるたびにバイトコードを解釈する代わりに、バイトコードを実行中のマシンのマシンコード命令にコンパイルし、これを呼び出します。代わりにオブジェクトコード。理想的には、オブジェクトコードの実行効率により、プログラムを実行するたびにプログラムを再コンパイルする非効率性が克服されます。


5
ただし、このフレーズ「Just-In-Time(JIT)コンパイラはランタイムインタープリタの機能です」は混乱を招きます。例えば- stackoverflow.com/questions/16439512/...
スティーブンC

11
実際、JITはアドオンであり、Javaの-Xintパラメータを使用して無効にすることができるため、これは単なる機能です。
クレイグトレーダー

3
私は完全に同意しません。JITは進化ではありません-それは古典的なコンパイラの代替です。
i486 2014年

1
JITは、機械式スイッチをハードワイヤリングすることから、スマートフォンに「OK Google」と言って検索条件を指定することへの進化の道のりの1ステップです。Java 7/8の一部として利用可能な現在のJITは、Java 2の一部として利用可能であったものを超えて飛躍的であり、それも進化です。
Craig Trader

1
@ i486-Sun / Oracleは(AFAIK)ネイティブコードを生成するJava用の古典的な(「前もって」)コンパイラを出荷していません。JITが代替案であると主張するのは一続きです...彼らがそれが代替案であると思われるものが出荷されなかったとき。(GCJ AOTコンパイラーは、Sun / Oracleとは関係がなく、完全なソリューションでもなかったため、割り引きます。現在、確実に実行可能ではありません。)
Stephen C

69

JIT-必要なときに(必要に応じて)単語自体が言う

典型的なシナリオ:

ソースコードは完全にマシンコードに変換されます

JITシナリオ:

ソースコードは、構造のようなアセンブリ言語に変換されます[C#の場合はex IL(中間言語)、javaの場合はByteCode]。

中間コードは、アプリケーションで必要なコードのみがマシンコードに変換される必要がある場合にのみ、マシン言語に変換されます。

JITと非JITの比較:

  • JITでは、すべてのコードが最初にマシンコードに変換されるわけではなく、必要なコードの一部がマシンコードに変換されます。次に、呼び出されたメソッドまたは機能がマシンにない場合、マシンコードに変換されます... CPUの負担。

  • マシンコードは実行時に生成されるため、JITコンパイラーは、マシンのCPUアーキテクチャーを実行するために最適化されたマシンコードを生成します。

JITの例:

  1. Java JITはJVM(Java Virtual Machine)にあります
  2. C#ではCLR(共通言語ランタイム)にあります
  3. Androidでは、新しいバージョンのDVM(Dalvik Virtual Machine)、またはART(Android RunTime)です。

7
JITは、実際のジェネリック型をサポートするフレームワークにいくつかの特別な利点を提供します。制限のないタイプのタイプを生成できるジェネリックメソッドを定義することが可能です。それぞれに異なるマシンコードが必要ですが、実際に生成されるタイプのコードのみをJITが生成します。対照的に、C ++では、コンパイラーがプログラムが使用するすべてのタイプのコードを生成する必要があります。
スーパーキャット2013

6
JVMは、初めて実行するときにJITコードを記述しません。最初の数回は、バイトコードを解釈します。次に、そのコードが十分に頻繁に実行されると、JITを実行することに煩わされる場合があります。
ninjalj 14年

1
あなたはJavaのJITがJVMだと言っています。ただし、コンパイル済みのコードはすでにJVMに提供されていますね。その後、それはそれを再びコンパイルしますか?
Koray Tugay 14

@KorayTugay-バイトコードをJVMに提供します。JVMはその一部をオンデマンドでマシンコードに変換します。リソースが節約されます。
Durai Amuthan.H 2015年

1
Javaでは、JITはJVMではありません。それはほんの一部です。
2015年

25

他の人が述べたように

JITはJust-in-Timeの略です。つまり、実行前ではなく、必要なときにコードがコンパイルされます。

上記の説明にポイントを追加するだけで、JVMは関数が実行された回数のカウントを維持します。このカウントが事前定義された制限を超えると、JITはコードをマシン言語にコンパイルし、プロセッサーが直接実行できるようにします(javacがコードをバイトコードにコンパイルしてからJavaに変換する通常の場合とは異なり-インタープリターはこのバイトコードを1行ずつ解釈して、マシンコードと実行)。

また、次回この関数が計算されるときには、コードが行ごとに再度解釈される通常の解釈とは異なり、同じコンパイル済みコードが再度実行されます。これにより、実行が速くなります。


14

JITコンパイラは、最初の実行時にバイトコードを同等のネイティブコードにコンパイルするだけです。連続して実行されるたびに、JVMはすでにコンパイルされたネイティブコードを使用してパフォーマンスを最適化するだけです。

ここに画像の説明を入力してください

JITコンパイラーがない場合、JVMインタープリターはバイトコードを1行ずつ変換して、ネイティブアプリケーションが実行されているかのように見せます。

ここに画像の説明を入力してください

ソース


1
私のJITの解釈は、頻繁に使用される関数が「格納」され、JavaバイトコードからネイティブのISA依存コードへのコンパイルのコストがバイパスされるメモ化のように機能するというものです。これが正しい場合、Javaが最初から完全にネイティブコードにコンパイルされないのはなぜですか?これは、あらゆる種類のランタイムコンパイルを削減し、Javaをマシンに対して「ネイティブ」にするでしょうか。
Michael Choi

12

JITはJust-in-Timeの略です。つまり、実行前ではなく、必要なときにコードがコンパイルされます。

コンパイラーは特定のマシン用に最適化されたコードを生成できるため、これは有益です。平均的なCコンパイラのような静的コンパイラは、開発者のマシンで実行可能なコードにすべてのコードをコンパイルします。したがって、コンパイラーはいくつかの仮定に基づいて最適化を実行します。ユーザーのプログラムの実行速度を低下させないため、コンパイルが遅くなり、最適化が多くなります。


コンパイルされたコードがユーザーのコンピューターのどこかに保存されていないのはなぜですか?次回アプリケーションが実行されるときに、JITはそれらを再コンパイルする必要がないのですか?
omerfarukdogan

良い観察。これを行うことは可能ですが、それが実際に有益かどうかは、プラットフォームとアプリの使用状況によって異なります。JITの最適化は、必ずしもオフラインまたは事前の最適化と同じであるとは限らないため、利点は「JITを実行しない」ことだけであり、あまり役に立たない場合があります。
ブライアンリトル2016年

9

バイトコード(アーキテクチャーに中立)がJavaコンパイラーによって生成された後、実行はJVM(Java)によって処理されます。ローダーによってバイトコードがJVMにロードされ、各バイト命令が解釈されます。

メソッドを複数回呼び出す必要がある場合は、同じコードを何度も解釈する必要があるため、必要以上に時間がかかる場合があります。したがって、JIT(ジャストインタイム)コンパイラがあります。バイトがJVMにロードされると(そのランタイム)、コード全体が解釈されるのではなくコンパイルされるため、時間を節約できます。

JITコンパイラーは実行時にのみ機能するため、バイナリー出力はありません。


2
コンパイルの方法についての情報(参照:ガイド)がほとんどないため、JVMにロードしてもコード全体はコンパイルされません。パフォーマンスが最終的な目標であることを覚えておいてください。JITはかなり選択的です。最適化のための最も一般的な方法を監視および選択します。そして、個々のメソッドの最大レベルの最適化に達するまで、これを続けます。
Yaw Boakye 2017

7

Just In Time Compiler(JIT):
Javaバイトコードをその特定のCPUのマシン命令にコンパイルします。

たとえば、Javaコードにループステートメントがある場合:

while(i<10){
    // ...
    a=a+i;
    // ...
 }

上記のループコードは、iの値が0の場合、10回実行されます。

同じ命令が10回実行されるため、バイトコードを10回コンパイルする必要はありません。その場合、そのコードを1回だけコンパイルする必要があり、必要な回数だけ値を変更できます。したがって、Just In Time(JIT)コンパイラーは、前述のようにそのようなステートメントとメソッドを追跡し、そのようなバイトコードをマシンコードにコンパイルしてパフォーマンスを向上させます。

同様の別の例は、文字列/文のリストで「正規表現」を使用してパターンを検索することです。

JITコンパイラは、すべてのコードをマシンコードにコンパイルするわけではありません。実行時に同様のパターンを持つコードをコンパイルします。

詳しくは、JITについてのOracleのドキュメントをご覧ください。


「同じ命令が10回実行されるので、バイトコードを10回何度もコンパイルする必要はありません」-通常のコンパイラはどうですか?この部分を数回コンパイルしますか?
TT_ 2018年

4

一部のIL(中間言語)に準拠したコードがあります。プログラムを実行すると、コンピューターはこのコードを理解しません。ネイティブコードのみを理解します。そのため、JITコンパイラは、ILをその場でネイティブコードにコンパイルします。これはメソッドレベルで行われます。


2
「メソッドレベル」とはどういう意味ですか?
Koray Tugay 14

4

私はこれが古いスレッドであることを知っていますが、ランタイムの最適化はJITコンパイルのもう1つの重要な部分であり、ここでは説明されていないようです。基本的に、JITコンパイラは実行時にプログラムを監視して、実行を改善する方法を決定できます。次に、実行時にそれらの変更をその場で行うことができます。Google JIT最適化(javaworldにはかなり良い記事があります。


3

ジャストインタイムコンパイラ(JIT)は、実行不可能な入力を受け取り、実行する適切なマシンコードを返すソフトウェアです。例えば:

Intermediate representation    JIT    Native machine code for the current CPU architecture

     Java bytecode            --->        machine code
     Javascript (run with V8) --->        machine code

この結果、特定のCPUアーキテクチャでは、適切なJITコンパイラをインストールする必要があります。

差分コンパイラー、インタープリター、およびJIT

ソースコードをマシンコードに変換したい場合、一般的には例外がありますが、以下を使用できます:

  1. コンパイラ:ソースコードを受け取り、実行可能ファイルを返します
  2. インタプリタ:プログラムを命令ごとに実行します。ソースコードの実行可能なセグメントを受け取り、そのセグメントを機械語命令に変換します。このプロセスは、すべてのソースコードが機械語命令に変換されて実行されるまで繰り返されます。
  3. JITJITの多くの異なる実装が可能ですが、JITは通常、コンパイラーとインタープリターの組み合わせです。JITは、最初に、中間データ(Javaバイトコードなど)を解釈によって機械語に変換します。多くの場合、JITはコードの特定の部分が頻繁に実行されることを感知でき、はこの部分をコンパイルして実行を高速化します。

2

Jitは、ジャストインタイムコンパイラの略です。jitは、Javaバイトコードを、プロセッサに直接送信できる命令に変換するプログラムです。

特定のシステムプラットフォームでJavaジャストインタイムコンパイラー(実際には2番目のコンパイラー)を使用すると、バイトコードが特定のシステムコードにコンパイルされます。コードがjitコンパイラーによって再コンパイルされると、通常、コンピューターでより速く実行されます。

ジャストインタイムコンパイラは仮想マシンに付属しており、オプションで使用されます。バイトコードをプラットフォーム固有の実行可能コードにコンパイルして、すぐに実行します。


2

ジャストインタイム(JIT)コンパイル(動的変換またはランタイムコンパイルも)は、実行前ではなく、プログラムの実行中に(実行時に)コンパイル含むコンピューターコード実行する方法です

ITは、コンパイルがあるの組み合わせ - 2つの伝統的なマシンコードに変換するためのアプローチ事前コンパイラ(AOT) 、および解釈 -との両方のいくつかの利点と欠点を兼ね備えています。JITコンパイルは、コンパイルされたコードの速度と解釈の柔軟性を兼ね備えています

JVMで使用されるJITを考えてみましょう、

たとえば、HotSpot JVM JITコンパイラは動的な最適化を生成します。つまり、Javaアプリケーションの実行中に最適化の決定を行い、基盤となるシステムアーキテクチャを対象とした高性能のネイティブマシン命令を生成します。

コンパイルするメソッドが選択されると、JVMはそのバイトコードをJust-In-Timeコンパイラー(JIT)にフィードします。JITは、メソッドを正しくコンパイルする前に、バイトコードのセマンティクスと構文を理解する必要があります。JITコンパイラーがメソッドを分析するのを助けるために、そのバイトコードは、最初にトレースツリーと呼ばれる内部表現で再構成されます。これは、バイトコードよりもマシンコードによく似ています。次に、メソッドのツリーに対して分析と最適化が実行されます。最後に、ツリーはネイティブコードに変換されます。

トレースツリーは、プログラミングコードのランタイムコンパイルで使用されるデータ構造です。トレースツリーは、ホットスポット中に実行されるコードを追跡してコンパイルする「ジャストインタイムコンパイラ」のタイプで使用されます。こちらをご覧ください。

参照:


1

非JITコンパイラはソースコードを受け取り、コンパイル時にマシン固有のバイトコードに変換します。JITコンパイラーは、コンパイル時に生成されたマシンに依存しないバイトコードを受け取り、実行時にそれをマシン固有のバイトコードに変換します。Javaが使用するJITコンパイラーは、単一のバイナリーを変更せずに多数のプラットフォームで実行できるようにするものです。


0

バイトコードの20%が80%の時間使用されます。JITコンパイラーはこれらの統計を取得し、インラインメソッドを追加したり、未使用のロックを削除したり、そのマシンに固有のバイトコードを作成したりすることで、バイトコードのこの20%を最適化して高速に実行します。私はこの記事から引用していますが、便利だと思いました。http://java.dzone.com/articles/just-time-compiler-jit-hotspot


これが-1とマークされた理由がわかりません。ここでのポイントは、ランタイム統計が最適化を支援するために使用されるということです。
2014

はい、しかし答えはそのようにそれを言っていませんでした。文字通り、JITはコードの最もホットな20%を最適化しません。
マブラハム2014

0

JITは、いくつかのJVM実装の実行エンジンを指します。1つは高速ですが、より多くのメモリを必要とし、ジャストインタイムコンパイラです。このスキームでは、メソッドが初めて呼び出されたときに、メソッドのバイトコードがネイティブマシンコードにコンパイルされます。次に、メソッドのネイティブマシンコードがキャッシュされるので、次に同じメソッドが呼び出されたときに再利用できます。


2
あなたが何か新しいもの/より良いものを提供しないなら、私はこのような質問に答えることを避けます。何らかの反応があった場合、それはおそらく反対票または批判です。あなたの答えは不正確です。「JIT」はJava仮想マシンに限定されず、「より高速ですがより多くのメモリを使用する」という効果はありますが、JITの概念に固有ではありません。メソッドは、最初の呼び出しではコンパイルされないことがよくあります。 JITに費やした時間は全体的に有利です。
zapl 2014年

0

JVMは、パフォーマンス上の理由から、実行時にコンパイルステップを実際に実行します。つまり、Javaにはコンパイルと実行が完全に分離されていません。まず、Javaソースコードからバイトコードへのいわゆる静的コンパイルを行います。次に、このバイトコードがJVMに渡されて実行されます。ただし、バイトコードの実行は遅いため、JVMはバイトコードの実行頻度を測定し、非常に頻繁に実行されるコードの「ホットスポット」を検出すると、バイトコードから「ホットスポット」コードのマシンコード(ホットスポットプロファイラー)への動的コンパイルを実行します。したがって、今日のJavaプログラムは、マシンコードの実行によって効果的に実行されます。


0

JITコンパイラーとしても知られるJust In Timeコンパイラーは、Javaのパフォーマンス向上に使用されます。デフォルトでは有効になっています。これは実行時にかなり早くコンパイルされます。Javaは、JITコンパイラーをJVMに組み込むことで、JITコンパイラーの使用を広めました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.