2012-05-02 5 views
16

Есть ли какие-либо практические применения операционного кода Java Virtual Machine NOP в сегодняшней JVM? Если да, то каковы сценарии, в которых NOP s будет сгенерирован в байт-коде?Что такое NOP в байт-коде JVM?

Мне было бы интересно увидеть пример кода Java, который скомпилируется в байт-код с NOP.


Update

MethodGen класс BCEL говорит,

При генерации кода может быть необходимо вставить операции NOP.

Я предполагаю, что другие библиотеки генерации байтокодов находятся в одной лодке, как указано в принятом ответе.

+0

Обычно он используется в коде отладки, чтобы разрешить точки останова на том, что не переводится в байт-код, например '{'. – vcsjones

+0

Вы имеете в виду, что это будет отображаться в байт-коде, когда файл Java будет скомпилирован с помощью 'javac -g'? – jbranchaud

+0

Я не верю, что 'javac' сделает это. Но другие компиляторы и отладчики могут использовать эту функциональность. – vcsjones

ответ

12

Некоторые случаи использования NOP байткодом предназначены для преобразования class файлов, оптимизации и статического анализа, выполненного инструментов, таких как Apache BCEL, ASM, FindBugs, PMD и т.д. Apache BCEL manual затрагивает некоторые использования NOP для целей анализа и оптимизации ,

JVM может использовать NOP байт-коды для оптимизации JIT для обеспечения того, чтобы блоки кода, находящиеся в синхронизации, были правильно выровнены, чтобы избежать false sharing.

Что касается некоторого примера кода, скомпилированного с использованием JDK javac, который содержит NOP байт-коды, это интересная задача. Однако я сомневаюсь, что компилятор будет генерировать любой файл class, содержащий NOP байт-коды с the bytecode instruction stream is only single-byte aligned. Мне было бы любопытно увидеть такой пример, но я не могу думать ни о себе.

1

Операции оптимизации процессоров часто не включаются. Я не уверен, в какой мере Java использует их в настоящее время.

От Wikipedia:

NOP, наиболее часто используется для целей синхронизации, чтобы заставить выравнивание памяти , чтобы предотвратить опасность, чтобы занять слот задержки ветви, или как место держатель должен быть заменен по действующим инструкциям позже в программе разработка (или для замены удаленных инструкций, когда рефакторинг будет быть проблематичным или трудоемким). В некоторых случаях NOP может иметь незначительные побочные эффекты ; например, на процессорах серии Motorola 68000, код операции NOP вызывает синхронизацию конвейера.

+6

Это имеет смысл в операционном коде физической машины, но что будет использовать такую ​​вещь для кода операции * virtual * machine? –

+0

Я ценю ответ, но этот вопрос касается конкретно JVM. – jbranchaud

2

Вот пример из некоторого кода я работаю над где инструкции NOP , где помещены в байт-код (как показано на Bytecode визуализатора для 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; 
} 

Я не уверен, почему они будут вставлены. Я просто надеюсь, что они не будут отрицательно влиять на производительность.

+3

Не существует 'nop', это всего лишь ошибка в Visualizer Visual Basic, которую вы использовали. Инструкция 'invokedynamic' состоит из пяти байтов, последние два из которых равны нулю для каждой спецификации. По-видимому, Visualizer Visual Basic не знает этого и предполагает, что команда 'invokedynamic' имеет только три байта и неверно интерпретирует два нулевых байта как инструкции« nop ». См. [JVM Spec invokedynamic] (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokedynamic). – Holger

+0

Я предполагаю, что это имеет смысл. Я жду обновления для Bytecode Visualizer для Eclipse Neon. Может быть, нам стоит сказать разработчику. – HesNotTheStig

Смежные вопросы