18

今日の JVM でJava 仮想マシンのNOPオペコードを実際に使用する方法はありますか? NOPもしそうなら、 s がバイトコードで生成されるいくつかのシナリオは何ですか?

sを使用してバイトコードにコンパイルされる Java コードの例も見たいと思いますNOP


アップデート

BCEL のMethodGenクラスによると、

コードの生成中に、NOP 操作を挿入する必要がある場合があります。

受け入れられた回答で指摘されたように、他のバイトコード生成ライブラリは同じ船に乗っていると思います。

4

3 に答える 3

12

一部のバイトコードの使用NOP例は、Apache BCELASMFindBugsPMDなどのclassツールによって実行されるファイル変換、最適化、および静的分析です。NOP

JVM はNOPJIT の最適化にバイトコードを使用して、同期セーフポイントにあるコード ブロックが適切に整列されていることを確認し、誤った共有を回避することができます。

バイトコードを含むJDKjavacコンパイラを使用してコンパイルされたサンプル コードについてはNOP、興味深い課題です。ただし、コンパイラがバイトコードclassを含むファイルを. そのような例を見たいと思っていますが、自分では思いつきません。NOPthe bytecode instruction stream is only single-byte aligned

于 2012-05-03T14:19:46.457 に答える
2

これは、nop命令がバイトコードに配置されている場所で作業しているコードの例です(Eclipse用のBytecode Visualizerで表示)

元のコード

public abstract class Wrapper<T extends Wrapper<T,E>,E>
  implements Supplier<Optional<E>>, Consumer<E>
{
  /** The wrapped object. */
  protected Optional<E> inner;

  /*
   * (non-Javadoc)
   * @see java.lang.Object#equals(java.lang.Object)
   */
  /**
   * A basic equals method that will compare the wrapped object to
   * whatever you throw at it, whether it is wrapped or not.
   */
  @Override
  public boolean equals(final Object that)
  {
    return this==that
        ||LambdaUtils.castAndMap(that,Wrapper.class,afterCast
            -> inner.equals(afterCast.inner))
        .orElseGet(()
            -> LambdaUtils.castAndMap(that,Optional.class,afterCast
                -> inner.equals(afterCast))
            .orElseGet(()
                -> Optional.ofNullable(that).map(thatobj
                    -> that.equals(inner.get()))
                .orElseGet(()
                    -> false)));
  }
}

equals(Object) メソッドの変換されたバイトコード

public boolean equals(java.lang.Object arg0) {
    /* L27 */
    0 aload_0;                /* this */
    1 aload_1;                /* that */
    2 if_acmpeq 36;
    /* L28 */
    5 aload_1;                /* that */
    6 ldc 1;
    8 aload_0;                /* this */
    9 invokedynamic 29;       /* java.util.function.Function apply(ext.cat.wcutils.collections.Wrapper arg0) */
    12 nop;
    13 nop;
    14 invokestatic 30;       /* java.util.Optional ext.cat.wcutils.util.LambdaUtils.castAndMap(java.lang.Object arg0, java.lang.Class arg1, java.util.function.Function arg2) */
    /* L30 */
    17 aload_0;               /* this */
    18 aload_1;               /* that */
    19 invokedynamic 39;      /* java.util.function.Supplier get(ext.cat.wcutils.collections.Wrapper arg0, java.lang.Object arg1) */
    22 nop;
    23 nop;
    24 invokevirtual 40;      /* java.lang.Object orElseGet(java.util.function.Supplier arg0) */
    27 checkcast 46;          /* java.lang.Boolean */
    30 invokevirtual 48;      /* boolean booleanValue() */
    /* L37 */
    33 ifne 5;
    /* L27 */
    36 iconst_0;
    37 ireturn;
    38 iconst_1;
    39 ireturn;
}

なぜそれらが挿入されるのかわかりません。それらがパフォーマンスに悪影響を及ぼさないことを願っています。

于 2015-10-22T18:56:52.140 に答える
0

多くの場合、プロセッサパイプラインの最適化のために操作は追加されません。Javaが現在それらをどの程度使用しているかはわかりません。

ウィキペディアから:

NOPは、タイミングの目的、メモリアライメントの強制、危険の防止、分岐遅延スロットの占有、またはプログラム開発の後半でアクティブな命令に置き換えられるプレースホルダーとして(または削除された命令を置き換えるときに最も一般的に使用されます)。リファクタリングは問題があるか、時間がかかります)。場合によっては、NOPは軽微な副作用をもたらす可能性があります。たとえば、Motorola 68000シリーズのプロセッサでは、NOPオペコードによってパイプラインの同期が発生します。

于 2012-05-02T22:19:05.770 に答える