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


112

Javaのインライン関数の概念はありますか?ある場合、それはどのように使用されますか?私はそれを聞いたpublicstaticfinalの方法は、インライン関数です。独自のインライン関数を作成できますか?


4
明確にするために、あなたはen.wikipedia.org/wiki/Anonymous_functionではなく、en.wikipedia.org/wiki/Inline_functionを意味しますよね?
JW。

3
小さなコメントとして、時期尚早の最適化はすべての悪の根源です。public、static、finalの性質を完全に理解しないと、インライン化の影響を理解することができません。これは、使用しているJVMに依存します。何かをインライン化する必要がある理由を最初に必ず答えてください。他の場所で実行できるより高いROI最適化があることはほぼ確実です。
Nathaniel Ford

回答:


123

Javaでは、最適化は通常JVMレベルで行われます。実行時に、JVMは「複雑な」分析を実行して、インライン化するメソッドを決定します。それはインライン化に積極的である可能性があり、ホットスポットJVMは実際には非最終メソッドをインライン化できます。

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

その他のリソース:

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

  2. Wiki:OpenJDKのインライン化。完全に入力されていませんが、役立つディスカッションへのリンクが含まれています。


15

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

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

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

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


3
finalJITインライン化に影響を与えない
Steve Kuo

1
+1、しかし、メソッドのコンパイルされたバージョンがインライン化されているかどうかをどのようにテストできますか?
パチェリエ

@Pacerierしかし、何かがインライン化されているかどうかをテストする必要があるのはなぜですか?
Arne Burmeister

14

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


3
ほとんどのJavaコンパイラーはメソッド呼び出しをインライン化しません。ほとんどの場合、JVMがそれを行います。
notnoop 2010年

それを明確にしてくれてありがとう。正確には、どのフェーズで発生したのかわかりませんでした。それを反映するように投稿を編集します。
Thomas Owens、

@ThomasOwensしますが、公開されていませんjdk.internal.vm.annotation.ForceInline
Eugene

4

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


5
finalメソッドはインラインであることが保証されていません。
Thomas Owens、

4
HotSpotでは、追加finalしても、メソッドがインライン化されているかどうかについては違いがありません。
トムホーティン-タックライン

4
@トーマス-私が「時々最終的な方法...」と言ったのはそのためです
GreenieMeanie 2010年

@ TomHawtin-tacklineそのための信頼できる情報源はありますか?私の知る限り、最終的なメソッドはタイプガードを使用せずにインライン化できます。つまり、修飾子を使用すると、修飾子を使用しない場合よりもメソッドのインライン化が効率的になります。インライン化するかどうかを決定するときに、Jikes RVMがこれを考慮に入れることを知っています。HotSpotが同じようなことをしないことを確信していますか?
Jannik Jochem 2015

2

実際の例:

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

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


1
これらはOracleのVMのデフォルト値です。docs.oracle.com
javase /

0

だから、そこにはないようですが、グアバまたは同等の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);

はい、これは、複雑なコードブロック({}内)を作成して、そのためのメソッドを作成することに煩わされるべきではない特定のことを行う方法を例示するためのデッドコードです(別名インライン)。


合理的な考えのようです。Googleの共通ライブラリを使用しないバージョンがありますか?
ragerdl 2017

0

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.