解析コール
この方法は、ターゲットメソッドがクラスのロードの解決フェーズでのシンボリック参照の定数プールで呼び出して、クラスファイルに直接参照へのシンボリック参照の一部となり、この決議はその提供:プログラムが実際に実行する前に、方法がありますコールはバージョンを決定することができるが、この方法のバージョンは不変実行時に呼び出される(理解コンパイル、ランナー不変)。これらのメソッドを呼び出すことは、解像度と呼ばれています。
Java仮想マシンのバイトコード命令5メソッド呼び出し:
- invokestatic:静的メソッドを呼び出します。
- invokespecial:インスタンスの初期化を呼び出します
メソッド、プライベートメソッドと親クラスのメソッド。 - INVOKEVIRTUAL:インスタンスメソッドの呼び出しオブジェクト。
- invokeinterface:インタフェースのメソッドを呼び出します。
- invokedynamicのターゲットとしてinvokedynamicの小数点命令を結合しているオブジェクトを呼び出すメソッドを呼び出します。
Java仮想マシン内で硬化させ、最初の4つの命令を、ディスパッチ・ロジック、およびユーザにより設定invokedynamicのディスパッチ・ロジックの案内方法が決定されます。
仮想メソッドのための(最後のメソッドを除く)他の非仮想メソッド呼び出し、呼び出されinvokestaticとinvokespecial方法。INVOKEVIRTUALが最後のコールので、カバーするように変更することはできませんので、それはまた、非仮想メソッドです。
派遣コール
解像度の呼び出しは、完全に再実行完了を延期するのではなく、コンパイル時に決定され、静的なプロセスである必要があります。ディスパッチ呼静的または動的であってもよいが、単一および複数のディスパッチディスパッチペアワイズ組合せに分割することができる静的単一割り当て、複数のディスパッチ静的、動的単一割当て、動的複数のディスパッチを構成しています。
図1に示すように、静的割り当て(複数ディスパッチ)
静的型測位方法ディスパッチに依存して静的割り当てと呼ばれるバージョンを実行します。一般的なアプリケーションをされて、オーバーロード。静的割り当ては、コンパイル時に発生する、いない仮想マシンに割り当てられたアクションが実行します。「より適切な」バージョンを確認することができコンパイルします。
public class StaticDispatch {
static abstract class Human{
}
static class Man extends Human{
}
static class Woman extends Human{
}
public static void sayHello(Human guy){
System.out.println("hello,guy!");
}
public static void sayHello(Man guy){
System.out.println("hello,gentlemen!");
}
public static void sayHello(Woman guy){
System.out.println("hello,lady!");
}
public static void main(String[] args) {
Human man=new Man();
Human woman=new Woman();
sayHello(man);
sayHello(woman);
}
}
輸出
hello,guy!
hello,guy!
2、動的割り当て(単一ディスパッチ)
実行時の型は、割り当ての実際の実行バージョンを決定する動的ディスパッチ法と呼ばれます。代表的なアプリケーションです書き換え。最初のステップは、直接参照を解決するために参照される定数プール、実行時に実際のINVOKEVIRTUAL命令受領者のタイプを決定するために、クラスメソッドINVOKEVIRTUALシンボルです。
public class DynamicDispatch {
static abstract class Human{
protected abstract void sayHello();
}
static class Man extends Human{
@Override
protected void sayHello() {
System.out.println("man say hello!");
}
}
static class Woman extends Human{
@Override
protected void sayHello() {
System.out.println("woman say hello!");
}
}
public static void main(String[] args) {
Human man=new Man();
Human woman=new Woman();
man.sayHello();
woman.sayHello();
man=new Woman();
man.sayHello();
}
}
出力:
man say hello!
woman say hello!
woman say hello!
図3に示すように、単一及び複数のディスパッチディスパッチ
受信機のパラメータおよび方法方法方法をまとめ量と呼ばれました。単一ディスパッチはターゲットメソッドの変数の選択で、ディスパッチは、複数の方法で標的複数の変数を選択します。
public class Dispatcher {
static class QQ {}
static class _360 {}
public static class Father {
public void hardChoice(QQ arg) {
System.out.println("father choose QQ");
}
public void hardChoice(_360 arg) {
System.out.println("father choose _360");
}
}
public static class Son extends Father {
@Override
public void hardChoice(QQ arg) {
System.out.println("son choose QQ");
}
@Override
public void hardChoice(_360 arg) {
System.out.println("son choose 360");
}
}
public static void main(String[] args) {
Father father = new Father();
Father son = new Son();
father.hardChoice(new _360());
son.hardChoice(new QQ());
}
}
輸出
father choose _360
son choose QQ
図4に示すように、仮想マシンの動的割り当てを達成します
最も一般的な「安定した最適化は、」クラスのvtableメソッド領域を理由から演奏するための手段を確立することである(Vritual方法表、vtableの、それに対応する、インターフェース-interfaceメソッド表、のITable)仮想メソッドテーブルインデックスを使用して、代わりに、メタデータ検索のパフォーマンスを向上させます。
実際のプロセスと各店舗ののVtableエントリアドレス。方法は、サブクラスでオーバーライドされていない場合、エントリ・アドレスの仮想メソッドテーブル・エントリ・アドレスと親クラスの同じメソッドのサブクラスは、親クラスの入口点を達成するために、同じです。子クラスは、このサブクラスのメソッドのメソッドをオーバーライドする場合は、実装のバージョンサブクラスを指すように、テーブル・エントリ・アドレスにアドレスを交換します。
変換のタイプは、テーブルルックアップの方法を変更することだけが必要である場合、異なるであろうように、方法と同じシグネチャを実装プログラムの便宜のために、親クラスvtableのサブクラスは、同じインデックス番号を有するべきです必要なインデックス・エントリ・アドレス変換により仮想メソッドテーブル。
クラスローディングの接続の初期化段階における一般的な方法のテーブルの後に、変数の型の初期値を調製し、クラスの仮想メソッドテーブルも初期化されます。
テーブルを使用する仮想マシンに加えて、それはまた、より高い性能の背面に基づいて、2つの非安定ラジカル最適化方法を用いて、インラインキャッシュとインナーガード型継承関係解析手法を使用する後期(実行時に)最適化を指します。
参考:「Java仮想マシン仕様(Java SEのバージョン8)「Java仮想マシン(第二版)、の深い理解」」。