1

メソッド/フィールドの可視性は、Java でのメソッドのインライン化にどのように影響しますか?

私が念頭に置いているケースは、フィールドのpublicゲッターのようなものです:private

private Thing blah;

public Thing getBlah() {
    return blah;
}

ここでいくつかの問題が発生します。

1 つは、Java コンパイラ自体がインライン展開を行うかどうかです。この質問には、イエスと言う人もいればノーと言う人もいて、さまざまな答えがあるようです。以前はインライン化を行わなかったが、現在はインライン化を行っているためなのか、それとも正しい人もいれば間違っている人もいるというだけなのかはわかりません...

getBlah()さて、インライン化を行う場合、呼び出しをインライン化できない可能性があると考えるのは正しいでしょうか? メソッドは非常に単純であり、メソッドを呼び出すオーバーヘッドはメソッド自体のコードと同じくらい大きいため、これらはインライン化が有用な場所であることは明らかです。privateしかし、コンパイラによってインライン化された場合、フィールドに直接アクセスするバイトコードになってしまいます。そして確かにJVMは文句を言うでしょうか?(これは、このメソッドが であっても適用されstatic finalます。)

第二に、JIT コンパイラーはどうですか? 私が見る限り、そのレベルでのインライン化に関しては、この問題は当てはまりません。ネイティブ コードが生成されると、JVM はすでにチェックを行っており、メソッドを呼び出すことができることを確認しています (これは であるためpublic)。そのため、可視性の問題なしに、呼び出しをインライン化するネイティブ コードを生成できます...はい?

4

3 に答える 3

1

javac コンパイラ (および任意の有効な Java コンパイラ) は、getter をインライン化せず、インライン化することもできません。考えてみてください。そのクラスからクラスを拡張し、ゲッターを上書きすることができます。そして、はい、コンパイラがそのアクセスを過度にインライン化すると、ベリファイアに合格しません(少なくともベリファイアに合格するべきではありませんが、すべてを検証するわけではありません-Java 1.3では、main()をプライベートにすることさえできますが、それでも作業...同様に、javacには-Oオプションがあり、コードを台無しにすることがありました)。

JIT はまったく別の獣です。メソッドのオーバーライトがあるかどうかはいつでも(少なくとも最近では)わかります。ゲッターを上書きするクラスが後でロードされた場合でも、既にJITされたメソッドを最適化解除して、継承ツリーの変更を反映できます (これは、AOT コンパイラーが情報を欠いている最適化の 1 つです)。

したがって、必要なものを安全にインライン化できます。また、アクセス修飾子を人為的に支持する必要もありません。コンパイルされたマシン コードにはそのようなものはなく、有効なコード変換とは何かを認識しているからです (また、getter は非常に一般的であるため、JIT が最適化)。

編集:完全に明確にするために、上記の段落は潜在的な仮想メソッドに対処しています。具体的には、プライベート、静的、または最終的なものではありません。Javac は場合によってはインライン化を実行できます。それらに対してオーバーライドが存在できないことが証明される可能性があるためです。JITもそれを行っているという事実に直面すると、それは無意味な仕事であり、JITの方がはるかに優れています。

于 2014-10-01T17:51:00.933 に答える
1
  1. javac getBlah()andのように単純であっても、メソッドをインライン化しません。setBlah()
  2. HotSpot JVM に関しては、インライン化の最大レベルに達しない限り、JIT コンパイラそのようなメソッドをすべてインライン化します ( -XX:MaxInlineLevel) 。
  3. JIT は、インライン化に関して同等に扱いpublic、メソッドを処理します。アクセス修飾子は、非常に特殊な場合privateを除き、一般にインライン化には影響しません。
于 2014-10-01T15:51:50.013 に答える