Java conjunto de instruções bytecode fornece várias formas de instrução dup . Estou tendo dificuldade para entender como essas instruções e da swap
instrução pode ser útil. O código java iria produzir bytecode com estas instruções quando compilado?
Variantes de dup
pode aparecer em código Java comum.
Por exemplo, como elaborado em esta resposta , objeto instanciação normalmente usa dup
, como new Object()
é compilado para
new #n // n referencing Class java.lang.Object in the pool
dup
invokespecial #m // m referencing Method java.lang.Object.<init>()V
Além disso, intArray[expression]++
é compilado para
… (code pushing the results of intArray and expression)
dup2
iaload
iconst_1
iadd
iastore
e, um apreciador bit
public static long example3(Long[] array, int i, long l) {
return array[i]=l;
}
compila para
0: aload_0
1: iload_1
2: lload_2
3: invokestatic #3 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
6: dup_x2
7: aastore
8: invokevirtual #4 // Method java/lang/Long.longValue:()J
11: lreturn
Alterando o tipo de matriz para long[]
produzir um exemplo dedup2_x2
Como discutido em este Q & A , javac
não usa swap
ou nop
(na implementação atual). Mas só porque javac
não usa uma instrução particular, não se pode presumir que nenhum compilador usa-lo.
Por exemplo, existem outros compiladores de Java, como ECJ
, mas não pode haver arquivos de classe criados por outras linguagens de programação ou estando já o resultado de uma ferramenta de instrumentação, que se torna relevante quando você quer código de instrumento em tempo de execução. E futuras versões do javac
também pode usar instruções eles não usaram antes, como antes Java 8, código Java não usar invokedynamic
.
Esta discussão aponta para um cenário, onde swap
seria apropriado. Ao usar try-with-recurso, não será gerado código, manipulação de uma exceção capturado enquanto já existe uma exceção capturada. Atuais javac
compila-lo (basicamente) para
astore n
aload o
aload n
invokevirtual #x // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
onde o
é a variável idade segurando a exceção já capturado e n
será uma variável inteiramente nova, o que não seria necessário ao compilar isso para
aload o
swap
invokevirtual #x // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
em vez de. Portanto, não é como estes instruções nunca foram necessários construções exóticos. É apenas um detalhe de implementação, quando um gerador de código específico não usá-los.
Falando de Instrumentação, também é importante ter em mente que um ClassFileTransformer
não é garantido para receber exatamente o mesmo bytecode como produzido pelo compilador. Pode ser um código de bytes equivalente.
Assim a linha inferior é, se você quiser implementar um ClassFileTransformer
, você deve estar preparado para lidar com cada byte código legal.