Javaでは、すべてのパブリック非静的メソッドは仮想です。これは、呼び出すメソッドが実行時に決定されることを意味します(動的バインディング)。C ++では、仮想関数(動的バインディング)はvpointerとvtableを使用して実装されます。これがJavaによってどのように実装されているか知りたいです。Javaは、実行時に呼び出すメソッドを知るために、C ++やその他の手法のようなvpointerとvtableも使用しますか?
4 に答える
https://wikis.oracle.com/display/HotSpotInternals/VirtualCallsで説明されているvtables
[編集Tomaszは質問コメントで良い点を述べています-これはOracleのホットスポット用です]
これは Java 仮想マシンの世界なので、話はそれほど単純ではありません。あなたができる最善のことは、さまざまな特殊なケースすべてに採用されている数十のトリックをすべて学ぶことです. これは悪い出発点ではありません: Inline caching .
すべての非静的メソッドが実行時にバインドされるわけではありません。多くの場合、メソッドのどのバージョンを呼び出す必要があるかは、コンパイル時に決定できます。特に、コンパイラーがどのメソッドを呼び出す必要があるかを 100% 確実に判断できる場合。そのような簡単な状況の 1 つ:
public class Foo {
public final void foo() { ... }
public void bar() { ... }
public void bar(String s) { ... }
}
Foo foo = new Foo();
// All three of these could would be bound at compile time.
foo.foo();
foo.bar();
foo.bar("baz");
コンパイル時のバインディングを決定できるオーバーロードに基づくケースもあります。さまざまなケースがすべて何であるかは 100% わかりませんが、いくつかあります。
この件に関する良い記事は次のとおりです。
http://www.dzone.com/links/r/difference_between_static_and_dynamic_binding_in.html
基本的に、仮想関数テーブルを使用して (概念的に) 実装され、それにインデックスが付けられます。しかし、多くの紆余曲折があり、特に「invokespecial」呼び出しとインターフェース呼び出しでは、追加/異なる処理が必要になります。
実際には、呼び出しの効率を向上させるために、多くのデータがキャッシュされます。