web-dev-qa-db-ja.com

Javaにインライン関数はありますか?

Javaにインライン関数の概念はありますか?ある場合、どのように使用されますか? publicstatic、およびfinalメソッドはインライン関数であると聞きました。独自のインライン関数を作成できますか?

104
giri

Javaでは、最適化は通常JVMレベルで行われます。実行時に、JVMは「複雑な」分析を実行して、インライン化するメソッドを決定します。インライン化を積極的に行うことができ、Hotspot JVMは実際には非最終メソッドをインライン化できます。

Javaコンパイラーは、メソッド呼び出しをインライン化することはほとんどありません(JVMは実行時にすべてを実行します)。インラインコンパイル時定数(最終的な静的プリミティブ値など)を実行します。しかし、メソッドではありません。

その他のリソース:

  1. 記事:Java HotSpot Performance Engine:メソッドのインライン化の例

  2. Wiki:OpenJDKのインライン化 、完全には実装されていませんが、有用な議論へのリンクが含まれています。

117
notnoop

Javaは、メソッドをインライン化することを手動で提案する方法を提供しません。 @notnoopがコメントで述べているように、インライン化は通常、実行時にJVMによって行われます。

14
Thomas Owens

いいえ、Javaには インライン関数 はありません。はい、パブリッククラスに配置すると、コード内の任意の場所でパブリック静的メソッドを使用できます。 Javaコンパイラーは、静的メソッドまたは最終メソッドで インライン展開 を実行できますが、それは保証されません。

通常、このようなコードの最適化は、非常に頻繁に使用されるコードセグメントのJVM/JIT/HotSpotと組み合わせてコンパイラーによって実行されます。また、パラメーターのレジスター宣言などのその他の最適化の概念は、Javaでは知られていません。

Javaの宣言によって最適化を強制することはできませんが、コンパイラとJITによって実行されます。他の多くの言語では、これらの宣言は多くの場合コンパイラのヒントにすぎません(プロセッサよりも多くのレジスタパラメーターを宣言できますが、残りは無視されます)。

Javaメソッドをstatic、final、またはprivateに宣言することも、コンパイラのヒントです。使用する必要がありますが、保証はありません。 Javaパフォーマンスは動的であり、静的ではありません。クラスの読み込みのため、システムへの最初の呼び出しは常に低速です。次の呼び出しは高速ですが、メモリとランタイムに応じて、実行中のシステム内で最も一般的な呼び出しが最適化されるため、実行中にサーバーが高速になる場合があります!

13
Arne Burmeister

あなたが言ったことは正しいです。最終メソッドはインラインとして作成されることもありますが、Javaでインライン関数を明示的に作成する他の方法はありません。

4
GreenieMeanie

実際の例:

public class Control {
    public static final long EXPIRED_ON = 1386082988202l;
    public static final boolean isExpired() {
        return (System.currentTimeMillis() > EXPIRED_ON);
    }
}

その後、他のクラスでは、コードの有効期限が切れたら終了できます。別のクラスからEXPIRED_ON変数を参照する場合、定数はバイトコードに対してインラインであるため、有効期限をチェックするコード内のすべての場所を追跡することは非常に困難です。ただし、他のクラスがisExpired()メソッドを呼び出すと、実際のメソッドが呼び出されます。つまり、ハッカーはisExpiredメソッドを常にfalseを返す別のメソッドに置き換えることができます。

コンパイラに静的なfinalメソッドを、それを参照するすべてのクラスにインライン化するように強制することは非常に素晴らしいことであることに同意します。その場合、実行時に不要になるため、Controlクラスを含める必要さえありません。

私の研究から、これはできません。おそらくいくつかのObfuscatorツールがこれを行うことができます。または、ビルドプロセスを変更して、コンパイルする前にソースを編集することもできます。

コンパイル中にコントロールクラスのメソッドが別のクラスにインラインで配置されているかどうかを証明するには、クラスパスでコントロールクラスなしで他のクラスを実行してみてください。

2
Billy Guthrie

Javaには「インライン」メソッドと呼ばれるメソッドがありますが、jvmに依存します。コンパイル後、メソッドのマシンコードが35バイト未満の場合、すぐにインラインメソッドに転送されます。メソッドのマシンコードが325バイト未満の場合、jvmに応じてインラインメソッドに転送できます。

2
Ethan

そうではないようですが、この回避策はグアバまたは同等のFunctionクラス実装を使用して使用できます。

    assert false : new com.google.common.base.Function<Void,String>(){
        @Override public String apply(Void input) {
            //your complex code go here
            return "weird message";
        }}.apply(null);

はい、これは複雑なコードブロック({}内)の作成方法を例示するためのデッドコードです。

0
Aquarius Power

Java9には、実行時ではなく、コンパイル時にいくつかの最適化を行う「Ahead of time」コンパイラーがあり、インライン化と見なすことができます。

0
tkruse