在今天的JVM中,Java虚拟机的NOP
操作码是否有任何实际用途?如果是这样,在字节码中生成NOP
的情况是什么?
我甚至有兴趣看到一个用NOP
s编译成字节码的Java代码示例。
更新
BCEL的MethodGen课程说,
在生成代码时,可能需要插入NOP操作。
我猜测其他字节代码库正在同一条船上,正如已接受的答案所指出的那样。
答案 0 :(得分:12)
一些NOP
字节码用例适用于class
文件转换,优化和静态分析,例如Apache BCEL,ASM,FindBugs,{ {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操作码导致管道同步。