This is a listing of the Java bytecode instructions grouped roughly into use cases. For instance, ifeq and goto belong to the Control Flow group.
What differentiates this list from the official instruction specification is that the descriptions have been modified to fit how Recaf represents them in the assembler.
NOTE: After creation of a new object, its constructor must properly be invoked to initialize the object. You will generally see the pattern:
// Given the code:
// String myString = new String(byteArrayHere);
new java/lang/String
dup
aload byteArrayHere
invokespecial java/lang/String.<init> ([B)V
astore myString
The new creates the initial instance.
The dup duplicates the reference to the instance on the stack.
The byte[] parameter to the String(byte[]) constructor is loaded on the stack.
The String(byte[]) constructor is invoked, consuming the byte[] paramter and the duplicatedString reference off of the stack.
The originally pushed String reference is stored in a variable.
Since the items from dup are the same instance this stores the String value after its constructor is called and initialization occurrs.
load a reference onto the stack from a local variable var
istore
var
value →
store int value into variable var
lstore
var
value →
store a long value in a local variable var
fstore
var
value →
store a float value into a local variable var
dstore
var
value →
store a double value into a local variable var
astore
var
objectref →
store a reference into a local variable var
iinc
var
amount
[No change]
increment local variable var by a given amount(byte)
NOTE: Variables are accessed by index in the class file specification, but Recaf's assembler maps variables to their name as found in the LocalVariableTable(LVT) attribute.
If a method does not have a LVT, or if the LVT contains bogus names that are not valid for use within the assembler, then auto-generated names will be used following the pattern v1, v2 ... vN.
insert a copy of the top value into the stack two (if value2 is double or long it takes up the entry of value3, too) or three values (if value2 is neither double nor long) from the top
invokes an interface method defined by the owner class and the method's name and desc on object objectref and puts the result on the stack (might be void)
invokespecial
owner
name
desc
objectref, [arg1, arg2, ...] → result
invokes an instance method defined by the owner class and the method's name and desc on object objectref and puts the result on the stack (might be void)
invokestatic
owner
name
desc
[arg1, arg2, ...] → result
invokes a static method defined by the owner class and the method's name and desc and puts the result on the stack (might be void)
invokevirtual
owner
name
desc
objectref, [arg1, arg2, ...] → result
invokes a virtual method defined by the owner class and the method's name and desc on object objectref and puts the result on the stack (might be void)
invokespecialinterface ✝
owner
name
desc
objectref, [arg1, arg2, ...] → result
invokes an instance method defined by the owner class and the method's name and desc on object objectref and puts the result on the stack (might be void)
invokestaticinterface ✝
owner
name
desc
[arg1, arg2, ...] → result
invokes a static method defined by the owner class and the method's name and desc and puts the result on the stack (might be void)
invokevirtualinterface ✝
owner
name
desc
objectref, [arg1, arg2, ...] → result
invokes a virtual method defined by the owner class and the method's name and desc on object objectref and puts the result on the stack (might be void)
NOTE: The ✝ instructions in the table above are abstractions in the Recaf assembler. These invoke_x_interface are variants of their respective invoke_x instructions with the itf flag set to true. This is normally not something you will encounter in properly compiled Java applications but has been found in some improperly processed classes in the wild (In particular the forge modding environment).
invokes a dynamic method and puts the result on the stack (might be void). The callsite handles the dynamic invocation.
NOTE: Before Java 9 - JEP 280String concatenation ("a" + "b") used StringBuilder to append multiple values together. Afterwards, concatenation was reimplemented to use invokedynamic. This instruction is the backbone of a lot of useful language features not only in just Java, but also other JVM languages.
Decompilers will often understand the specific usages for cases found in the standard Java language, but will often fail for third party languages or within auto-generated / obfuscated code.