在當今的JVM中,Java虛擬機的NOP
操作碼是否有任何實際用途?如果是這樣,那麼在字節碼中會產生哪些場景NOP
?用於JVM字節碼的NOP是什麼?
我甚至有興趣看到一個編碼爲NOP
的字節碼的Java代碼的例子。
更新
BCEL的MethodGen班說,
在生成代碼,可能需要插入NOP操作。
我在猜測其他的字節碼生成庫在同一條船上,正如在接受的答案中指出的那樣。
在當今的JVM中,Java虛擬機的NOP
操作碼是否有任何實際用途?如果是這樣,那麼在字節碼中會產生哪些場景NOP
?用於JVM字節碼的NOP是什麼?
我甚至有興趣看到一個編碼爲NOP
的字節碼的Java代碼的例子。
更新
BCEL的MethodGen班說,
在生成代碼,可能需要插入NOP操作。
我在猜測其他的字節碼生成庫在同一條船上,正如在接受的答案中指出的那樣。
一些NOP
字節碼的使用情況是class
文件變換,優化和工具進行靜態分析,如Apache BCEL,ASM,FindBugs,PMD等對NOP
一些使用Apache BCEL manual觸摸進行分析和優化的目的。
JVM可能使用NOP
字節碼進行JIT優化,以確保處於同步安全點的代碼塊正確對齊以避免false sharing。
對於使用包含NOP
字節碼的JDK javac
編譯器編譯的一些示例代碼,這是一個有趣的挑戰。不過,我懷疑編譯器會自the bytecode instruction stream is only single-byte aligned
以後生成包含NOP
字節碼的任何class
文件。我會很好奇看到這樣一個例子,但我想不出自己。
通常不會爲操作系統優化添加操作。我不確定Java目前在多大程度上使用它們。
甲NOP最常用於定時目的,以迫使存儲器 對準,以防止危害,以佔據分支延遲槽中,或作爲 佔位符被替換通過活動指令稍後在程序 開發中(或者當重構將 有問題或耗時時替換移除的指令)。在某些情況下,NOP可能有輕微的副作用;例如,在Motorola 68000系列處理器上, NOP操作碼會導致管道同步。
這在物理機器操作碼中是有意義的,但是對於虛擬機器操作碼會有什麼用? –
我很欣賞答案,但這個問題是關於JVM的非常具體。 – jbranchaud
下面是一些代碼,我已經工作的示例,其中,其中放置到字節碼(如由字節碼展示臺爲Eclipse看去)NOP指令
原始代碼
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)));
}
}
等於(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;
}
我不確定爲什麼要插入這些字節碼。我只希望他們不會對性能產生負面影響。
沒有'nop',這只是您使用的Bytecode Visualizer中的一個錯誤。 'invokedynamic'指令由五個字節組成,最後兩個字節爲每個規範零。顯然,Bytecode Visualizer並不知道這一點,並假定'invokedynamic'指令只有三個字節,並將兩個零字節誤解爲'nop'指令。請參閱[JVM規範invokedynamic](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokedynamic)。 – Holger
我想這是有道理的。我在等待更新Bytecode Visualizer for Eclipse Neon。也許我們應該告訴開發者。 – HesNotTheStig
通常在調試代碼中使用它來允許某些不轉換爲字節碼的斷點,如'{'。 – vcsjones
你的意思是說,當使用'javac -g'編譯Java文件時,這會出現在字節碼中? – jbranchaud
我不相信'javac'會這樣做。但其他編譯器和調試器可以使用該功能。 – vcsjones