42

C++には多重継承があります。アセンブリレベルでの多重継承の実装は非常に複雑になる可能性がありますが、これが通常どのように行われるかについてはオンラインで適切な説明があります(vtables、ポインター修正、サンクなど)。

Javaには複数の実装継承はありませんが、複数のインターフェース継承があるため、クラスごとに1つのvtableを使用する単純な実装ではそれを実装できないと思います。Javaはどのようにインターフェースを内部的に実装しますか?

C ++とは異なり、JavaはJitでコンパイルされるため、コードの断片が異なれば最適化も異なり、JVMも異なると動作が異なる可能性があることを認識しています。それで、多くのJVMがこれに従ういくつかの一般的な戦略がありますか、または誰かが特定のJVMでの実装を知っていますか?

また、JVMは多くの場合、仮想化を解除してメソッド呼び出しをインライン化します。この場合、vtableまたは同等のものはまったく含まれないため、仮想/インターフェイスメソッド呼び出しを実装する実際のアセンブリシーケンスについて質問するのは意味がないかもしれませんが、ほとんどのJVMはまだいくつかを保持していると思いますすべてを非仮想化できなかった場合に使用するクラスの一般的な表現の一種。この仮定は間違っていますか?この表現はC++vtableのように見えますか?その場合、インターフェイスには個別のvtableがあり、これらはクラスvtableとどのようにリンクされていますか?もしそうなら、C ++のオブジェクトインスタンスのように、オブジェクトインスタンスは(クラス/インターフェイスvtablesへの)複数のvtableポインタを持つことができますか?同じオブジェクトへのクラスタイプとインターフェイスタイプの参照は常に同じバイナリ値を持ちますか、それともポインターの修正が必要なC ++のようにこれらが異なる可能性がありますか?

(参照:この質問はCLRについて同様の質問をします。このmsdnの記事には、今では時代遅れになっているかもしれませんが、良い説明があるようです。Javaに似たものは見つかりませんでした。)

編集:

  • 「JavaクラスArrayListがListインターフェースを実装する」という意味ではなく、「GCCコンパイラが整数加算/関数呼び出しなどをどのように実装するか」という意味で「実装」を意味します。
  • これがJVMバイトコードレベルでどのように機能するかを知っています。知りたいのは、クラスファイルのロードとバイトコードのコンパイルが完了した後にJVMによって生成されるコードとデータ構造の種類です。
4

1 に答える 1

29

HotSpot JVMの主な機能は、インラインキャッシングです。。これは、実際にはターゲットメソッドがインライン化されていることを意味するのではなく、仮想メソッドまたはインターフェイスメソッドへの今後のすべての呼び出しがまったく同じ実装をターゲットにする(つまり、呼び出しサイトが単相である)という仮定がJITコードに組み込まれることを意味します。この場合、仮定が実際に成立するかどうか(つまり、ターゲットオブジェクトのタイプが前回と同じかどうか)のチェックがマシンコードにコンパイルされ、仮想テーブルなしで制御をターゲットメソッドに直接転送します。まったく関与しました。アサーションが失敗した場合、これをメガモーフィックコールサイトに変換しようとする可能性があります(つまり、複数の可能なタイプを使用)。これも失敗した場合(または最初の呼び出しの場合)、vtables(仮想メソッドの場合)とitables(インターフェイスの場合)を使用して、通常の長時間のルックアップが実行されます。

編集 Hotspot Wikiには、vtableおよびitableスタブの詳細があります。多態的な場合でも、インラインキャッシュバージョンを呼び出しサイトに配置します。ただし、コードは実際にはvtableまたはitableでルックアップを実行するスタブです。vtableオフセット(0、1、2、...)ごとに1つのvtableスタブがあります。インターフェイス呼び出しは、指定されたオフセットでitable(見つかった場合)を調べる前に、itableの配列に対して線形検索を追加します。

于 2010-12-12T21:18:15.777 に答える