Javaのインライン関数の概念はありますか?ある場合、それはどのように使用されますか?私はそれを聞いたpublic
、static
とfinal
の方法は、インライン関数です。独自のインライン関数を作成できますか?
Javaのインライン関数の概念はありますか?ある場合、それはどのように使用されますか?私はそれを聞いたpublic
、static
とfinal
の方法は、インライン関数です。独自のインライン関数を作成できますか?
回答:
Javaでは、最適化は通常JVMレベルで行われます。実行時に、JVMは「複雑な」分析を実行して、インライン化するメソッドを決定します。それはインライン化に積極的である可能性があり、ホットスポットJVMは実際には非最終メソッドをインライン化できます。
Javaコンパイラーがメソッド呼び出しをインライン化することはほとんどありません(JVMは実行時にそのすべてを行います)。これらは、インラインコンパイル時定数(最終的な静的プリミティブ値など)を実行します。しかし、メソッドではありません。
その他のリソース:
Wiki:OpenJDKのインライン化。完全に入力されていませんが、役立つディスカッションへのリンクが含まれています。
いいえ、Java にはインライン関数はありません。はい、パブリック静的メソッドをパブリッククラスに配置すると、コードの任意の場所で使用できます。Javaコンパイラは静的メソッドまたは最終メソッドでインライン展開を行う場合がありますが、これは保証されていません。
通常、このようなコードの最適化は、非常に頻繁に使用されるコードセグメントのJVM / JIT / HotSpotと組み合わせてコンパイラーによって行われます。また、パラメーターのレジスター宣言などの他の最適化の概念は、Javaでは知られていません。
最適化はJavaでの宣言によって強制することはできませんが、コンパイラとJITによって行われます。他の多くの言語では、これらの宣言はコンパイラのヒントにすぎないことがよくあります(プロセッサの数よりも多くのレジスタパラメータを宣言できますが、残りは無視されます)。
Javaメソッドをstatic、final、またはprivateとして宣言することも、コンパイラーのヒントです。あなたはそれを使うべきですが、保証はありません。Javaのパフォーマンスは静的ではなく動的です。クラスの読み込みのため、システムへの最初の呼び出しは常に遅くなります。次の呼び出しはより高速ですが、メモリとランタイムに応じて、最も一般的な呼び出しは実行中のシステム内で最適化されるため、ランタイム中にサーバーが高速になる可能性があります。
final
JITインライン化に影響を与えない
Javaは、メソッドをインライン化する必要があることを手動で提案する方法を提供していません。コメントで@notnoopが言うように、インライン化は通常、実行時にJVMによって行われます。
jdk.internal.vm.annotation.ForceInline
あなたが上で言ったことは正しいです。finalメソッドはインラインとして作成されることもありますが、Javaでインライン関数を明示的に作成する方法は他にありません。
final
しても、メソッドがインライン化されているかどうかについては違いがありません。
実際の例:
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ツールでこれを実行できます。または、コンパイルする前にビルドプロセスを変更してソースを編集することもできます。
コンパイル中にコントロールクラスからのメソッドが別のクラスにインラインで配置されているかどうかを証明するには、クラスパスにコントロールクラスなしで他のクラスを実行してみてください。
まあ、Javaでは「インライン」メソッドと呼ぶことができるメソッドがありますが、jvmによって異なります。コンパイル後、メソッドのマシンコードが35バイト未満の場合は、すぐにインラインメソッドに転送されます。メソッドのマシンコードが325バイト未満の場合は、jvmに応じて、インラインメソッドに転送できます。
だから、そこにはないようですが、グアバまたは同等の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);
はい、これは、複雑なコードブロック({}内)を作成して、そのためのメソッドを作成することに煩わされるべきではない特定のことを行う方法を例示するためのデッドコードです(別名インライン)。