JVM字节码中的NOP用于什么?

时间:2012-05-02 21:36:08

标签: java jvm bytecode nop

在今天的JVM中,Java虚拟机的NOP操作码是否有任何实际用途?如果是这样,在字节码中生成NOP的情况是什么?

我甚至有兴趣看到一个用NOP s编译成字节码的Java代码示例。


更新

BCEL的MethodGen课程说,

  

在生成代码时,可能需要插入NOP操作。

我猜测其他字节代码库正在同一条船上,正如已接受的答案所指出的那样。

3 个答案:

答案 0 :(得分:12)

一些NOP字节码用例适用于class文件转换,优化和静态分析,例如Apache BCELASMFindBugs,{ {3}}等.Apache PMD涉及NOP的某些用途,用于分析和优化。

JVM可以使用NOP字节码进行JIT优化,以确保处于同步安全点的代码块正确对齐以避免BCEL manual

对于使用包含javac字节码的JDK NOP编译器编译的一些示例代码,这是一个有趣的挑战。但是,我怀疑编译器将生成自false sharing以来包含class字节码的任何NOP文件。我很想看到这样一个例子,但我自己也想不到。

答案 1 :(得分:2)

以下是一些我一直在研究nop指令的代码的例子 放在字节代码中的位置(由Bytecode Visualizer for Eclipse查看)

原始代码

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;
}

我不确定为什么会插入这些内容。我只是希望它们不会对性能产生负面影响。

答案 2 :(得分:1)

通常不会为处理器管道优化添加操作。我不确定Java目前使用它们的程度。

来自Wikipedia

  

NOP最常用于计时目的,以强制记忆   对齐,防止危险,占用分支延迟槽,或作为   占位符将在稍后的程序中被活动指令替换   开发(或在重构时替换已删除的指令)   有问题或耗时)。在某些情况下,NOP可能会有轻微的   副作用;例如,在Motorola 68000系列处理器上,   NOP操作码导致管道同步。