2つの単純なクラスから始めましょう。
package com.michaelt.so.supers;
public class Sup {
int methodA(int a, int b) {
return a + b;
}
}
その後
package com.michaelt.so.supers;
public class Sub extends Sup {
@Override
int methodA(int a, int b) {
return super.methodA(a, b);
}
}
methodAをコンパイルして、取得するバイトコードを確認します。
methodA(II)I
L0
LINENUMBER 6 L0
ALOAD 0
ILOAD 1
ILOAD 2
INVOKESPECIAL com/michaelt/so/supers/Sup.methodA (II)I
IRETURN
L1
LOCALVARIABLE this Lcom/michaelt/so/supers/Sub; L0 L1 0
LOCALVARIABLE a I L0 L1 1
LOCALVARIABLE b I L0 L1 2
MAXSTACK = 3
MAXLOCALS = 3
そして、SupクラスmethodA()に対してルックアップを行うinvokespecialメソッドですぐに確認できます。
invokespecialオペコードは、以下の論理があります。
- Cに、解決されたメソッドと同じ名前と記述子を持つインスタンスメソッドの宣言が含まれている場合、このメソッドが呼び出されます。検索手順は終了します。
- それ以外の場合で、Cにスーパークラスがある場合、この同じルックアップ手順は、Cの直接スーパークラスを使用して再帰的に実行されます。呼び出されるメソッドは、このルックアップ手順の再帰的な呼び出しの結果です。
- それ以外の場合、AbstractMethodErrorが発生します。
この場合、クラスに同じ名前と記述子を持つインスタンスメソッドがないため、最初の弾丸は発火しません。ただし、2番目の弾丸は、スーパークラスがあり、スーパーのmethodAを呼び出します。
コンパイラーはこれをインライン化せず、クラスにSupのソースのコピーはありません。
しかし、物語はまだ終わっていません。これはコンパイルされたコードです。コードがJVMに到達すると、 HotSpotが関与できるようになります。
残念ながら、それについてはあまり知りませんので、この件について当局に訴え、Javaのインライン化にアクセスします。ここでは、HotSpot がメソッド(非最終メソッドも)をインライン化できると言われています。
行くドキュメントサブmethodAに)効果的燮methodAからコードを(コピー() -それはその特定のメソッドの呼び出しではなく、それぞれの時間を検索、この情報はインライン化できることをやってのホットスポットとなる場合が注目されます。
これは、アプリケーションがどのように動作しているか、およびパフォーマンスを高速化するために必要な最適化に基づいて、実行時にメモリ内で行われます。
OpenJDKのHotSpot内部で述べられているように、「メソッドはしばしばインライン化されます。静的、プライベート、最終、および/または「特別な」呼び出しは簡単にインライン化できます。」
JVMのオプションを掘り下げる-XX:MaxInlineSize=35
と、インライン化できる最大バイト数であるオプション(35がデフォルト)が見つかります。Javaが簡単にインライン化できるので、Javaが多くの小さなメソッドを好むのはこのためです。これらの小さなメソッドは、インライン化できるため、より多く呼び出されると高速になります。そして、その数を試して大きくすることはできますが、他の最適化の効果が低下する可能性があります。(関連するSOの質問:HotSpotが行っていることのインライン化の内部を覗くための他の多くのオプションを指摘するHotSpot JITインライン化戦略)。
したがって、いいえ-コードはコンパイル時にインライン化されません。そして、はい-パフォーマンスの最適化が必要であれば、コードは実行時にインライン化される可能性が非常に高いです。
そして、私がHotSpotインライン化について書いたものはすべて、Oracleが配布したHotSpot JVMにのみ適用されます。ウィキペディアのJava仮想マシンのリストを見ると、HotSpot以外にも多くのものがあり、これらのJVMがインライン化を処理する方法は、上で説明した方法とはまったく異なる場合があります。Apache Harmony、Dalvik、ART-状況によって動作が異なる場合があります。