39

バイトコードでできることはすべて、ネイティブ コードでも同じように簡単かつはるかに高速に実行できるように思えます。理論的には、プログラムとライブラリをバイトコードで配布し、インストール時に JIT ではなくネイティブ コードにコンパイルすることで、プラットフォームと言語の独立性を維持することもできます。

一般的に、ネイティブの代わりにバイトコードを実行したいのはいつですか?

4

8 に答える 8

31

SGI の Hank Shiffman は次のように述べています (かなり前のことですが、今でも真実です)。

システムのネイティブ コードではなくバイト コードを使用する Java には、次の 3 つの利点があります。

  1. 携帯性: 各種類のコンピューターには、独自の命令セットがあります。一部のプロセッサには、以前のプロセッサ用の命令が含まれていますが、通常、ある種類のコンピュータで実行されるプログラムは、他のコンピュータでは実行されません。各システムが独自の方法で記述するオペレーティング システムによって提供されるサービスを追加すると、互換性の問題が発生します。一般に、ある種類のシステム用にプログラムを作成してコンパイルし、多くの作業を行わずに他のシステムで実行することはできません。Java は、アプリケーションと実際の環境 (コンピューター + オペレーティング システム) の間に仮想マシンを挿入することで、この制限を回避します。アプリケーションが Java バイト コードにコンパイルされ、そのバイト コードがすべての環境で同じように解釈される場合、Java がサポートされているすべての異なるプラットフォームで動作する単一のプログラムを作成できます。(とにかく、それが理論です。実際には、プログラマーを待ち受けている小さな非互換性が常に存在します。)

  2. 安全: Java の長所の 1 つは、Web への統合です。Java を使用する Web ページをブラウザにロードすると、Java コードが自動的にダウンロードされて実行されます。しかし、コードがファイルを破壊した場合はどうなるでしょうか? 悪意によるものか、プログラマー側のずさんな行為によるものかは関係ありません。Java は、潜在的に危険な操作を禁止することで、ダウンロードされたアプレットが破壊的なことを行うのを防ぎます。コードの実行を許可する前に、セキュリティをバイパスする試みがないか調べます。データが一貫して使用されていることを確認します。ある段階でデータ項目を整数として操作し、後でそれをポインターとして使用しようとするコードは、キャッチされ、実行が妨げられます。(Java 言語ではポインター演算が許可されていないため、ここで説明したことを行う Java コードを作成することはできません。ただし、誰かが 16 進エディタを使用して破壊的なバイト コードを自分で作成したり、Java バイト コード アセンブラを作成したりすることを妨げるものは何もありません)。一般に、実行前にプログラムのマシン コードを分析し、何か問題があるかどうかを判断することはできません。自己変更コードを書くなどのトリックは、悪意のある操作が後になって初めて存在する可能性があることを意味します。しかし、Java バイト コードは、この種の検証用に設計されています。悪意のあるプログラマーが攻撃を隠すために使用する命令は含まれていません。自己変更コードを書くなどのトリックは、悪意のある操作が後になって初めて存在する可能性があることを意味します。しかし、Java バイト コードは、この種の検証用に設計されています。悪意のあるプログラマーが攻撃を隠すために使用する命令は含まれていません。自己変更コードを書くなどのトリックは、悪意のある操作が後になって初めて存在する可能性があることを意味します。しかし、Java バイト コードは、この種の検証用に設計されています。悪意のあるプログラマーが攻撃を隠すために使用する命令は含まれていません。

  3. サイズ: マイクロプロセッサの世界では、CISC よりも RISC の方が一般的に好まれます。多くの複雑な操作を単一の命令として実装するよりも、小さい命令セットを使用して多くの高速な命令を使用してジョブを実行する方が適切です。RISC 設計では、チップ上で命令を実装するために必要なゲートが少なくて済み、パイプラインやその他の手法を使用して各命令を高速化する余地が増えます。しかし、インタプリタでは、これは重要ではありません。case 句の数に応じて可変長の switch ステートメントに単一の命令を実装する場合は、そうしない理由はありません。実際、複雑な命令セットは Web ベースの言語の利点です。つまり、同じプログラムがより小さくなります (より複雑な命令が少なくなります)。

したがって、バイト コードとネイティブ コードを検討するときは、移植性、セキュリティ、サイズ、および実行速度の間でどのようなトレードオフを行うかを検討してください。速度が唯一の重要な要素である場合は、ネイティブに移行してください。他に重要なものがある場合は、バイトコードを使用してください。

また、リリースごとに同じコード ベースの一連の OS およびアーキテクチャ ターゲットのコンパイルを維持することは、非常に面倒になる可能性があることも付け加えておきます。複数のプラットフォームで同じ Java バイトコードを使用し、それを「そのまま動作させる」ことは大きなメリットです。

于 2008-09-07T04:46:27.147 に答える
15

プログラムをコンパイルし、プロファイリングを使用して実行し、その結果を 2 回目のパスでコンパイラにフィードバックすると、基本的にすべてのプログラムのパフォーマンスが向上します。実際に使用されるコード パスはより積極的に最適化され、ループは適切な程度にアンロールされ、ホット命令パスは I$ ヒットを最大化するように配置されます。

すべてが良いことですが、バイナリを構築するために非常に多くの手順を踏むのは面倒なので、ほとんど完了していません。

これは、バイトコードをネイティブ コードにコンパイルする前にしばらく実行する利点です。プロファイリング情報が自動的に利用可能になります。Just-In-Time コンパイルの結果は、プログラムが処理している特定のデータに対して高度に最適化されたネイティブ コードになります。

バイトコードを実行できると、静的コンパイラが安全に使用できるよりも積極的なネイティブ最適化も可能になります。たとえば、関数の引数の 1 つが常に NULL であることが示されている場合、その引数のすべての処理をネイティブ コードから単純に省略できます。関数プロローグで引数の簡単な有効性チェックが行われます。その引数が NULL でない場合、VM はバイトコードに戻り、プロファイリングを再開します。

于 2008-09-07T04:56:01.210 に答える
9

バイトコードは、余分なレベルの間接性を作成します。

この追加レベルの間接化の利点は次のとおりです。

  • プラットフォームの独立性
  • 任意の数のプログラミング言語 (構文) を作成し、それらを同じバイトコードにコンパイルできます。
  • クロス言語コンバーターを簡単に作成できる
  • x86、x64、および IA64 を個別のバイナリとしてコンパイルする必要がなくなりました。適切な仮想マシンのみをインストールする必要があります。
  • 各 OS で仮想マシンを作成するだけで、同じプログラムがサポートされます。
  • ジャスト イン タイム コンパイルを使用すると、パッチが適用された単一のソース ファイルを置き換えるだけで、プログラムを更新できます。(ウェブページに非常に有益です)

欠点のいくつか:

  • パフォーマンス
  • 逆コンパイルしやすい
于 2008-09-07T04:44:07.027 に答える
3

すべての良い答えですが、私のホットボタンが打たれました - パフォーマンス。

実行中のコードがすべての時間をライブラリ/システム ルーチンの呼び出し (ファイル操作、データベース操作、Windows メッセージの送信) に費やしている場合、それが JIT されているかどうかはあまり問題ではありません。レベルの操作を完了します。

ただし、通常「アルゴリズム」と呼ばれるものがコードに含まれている場合、それらは高速で関数の呼び出しに多くの時間を費やさなければならず、それらがパフォーマンスの問題になるほど頻繁に使用される場合、JIT は非常に重要です。

于 2009-01-06T21:22:27.030 に答える
2

ここ: http://slashdot.org/developers/02/01/31/013247.shtml

Slashdot のオタクがそれについて何と言っているか見てみましょう! 少し古いですが、非常に良いコメントです!

于 2008-09-07T04:56:24.377 に答える
2

プラットフォームの独立性というご自身の質問に答えただけだと思います。プラットフォームに依存しないバイトコードが生成され、ターゲット プラットフォームに配布されます。実行されると、実行が開始される前、または同時に (ジャスト イン タイム) ネイティブ コードにすばやくコンパイルされます。Java JVM とおそらく .NET ランタイムは、この原則に基づいて動作します。

于 2008-09-07T04:38:45.667 に答える
1

理想的には、ジャスト イン タイムをネイティブ コードにコンパイルする移植可能なバイトコードが必要です。JIT なしでバイトコード インタープリターが存在する理由は、主に、ネイティブ コードのコンパイルによって仮想マシンが複雑になるという実際的な事実によるものだと思います。その追加コンポーネントのビルド、デバッグ、および保守には時間がかかります。誰もがその約束をするための時間やリソースを持っているわけではありません。

二次的な要因は安全性です。ネイティブ コードで同じことを保証するよりも、インタープリターがクラッシュしないことを確認する方がはるかに簡単です。

3つ目はパフォーマンスです。一度だけ実行される小さなコードのバイトコードを解釈するよりも、機械語を生成する方が時間がかかることがよくあります。

于 2008-09-07T04:50:06.670 に答える
0

ネイティブ コードに対するバイトコードの最も顕著な利点は、おそらく移植性とプラットフォームの独立性です。

于 2013-04-24T19:32:01.423 に答える