JVM Bytecode Instructions

Preface

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.

Table of Contents

Constants

OpcodeStack: [before]→[after]Description
aconst_nullnullpush a null reference onto the stack
dconst_00.0push the constant 0.0 onto the stack
dconst_11.0push the constant 1.0 onto the stack
fconst_00.0fpush 0.0f on the stack
fconst_11.0fpush 1.0f on the stack
fconst_22.0fpush 2.0f on the stack
iconst_m1-1load the int value −1 onto the stack
iconst_00load the int value 0 onto the stack
iconst_11load the int value 1 onto the stack
iconst_22load the int value 2 onto the stack
iconst_33load the int value 3 onto the stack
iconst_44load the int value 4 onto the stack
iconst_55load the int value 5 onto the stack
lconst_00Lpush long 0L onto the stack
lconst_11Lpush long 1L onto the stack
ldc
  • value
→ valuepush a constant value (String, int, float, long, double, Class, MethodType, MethodHandle, or ConstantDynamic) onto the stack
bipush
  • value
→ valuepush a byte (-128 through 127) onto the stack as an int value
sipush
  • value
→ valuepush a short (-32768 through 32767) onto the stack as an int value

Object Creation

OpcodeStack: [before]→[after]Description
new
  • type
→ objectrefcreate new object of type

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
  1. The new creates the initial instance.
  2. The dup duplicates the reference to the instance on the stack.
  3. The byte[] parameter to the String(byte[]) constructor is loaded on the stack.
  4. The String(byte[]) constructor is invoked, consuming the byte[] paramter and the duplicated String reference off of the stack.
  5. 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.

Arrays

OpcodeStack: [before]→[after]Description
anewarray
  • type
count → arrayrefcreate a new array of references of length count and component type identified by type (A full class name such as java/lang/String)
newarray
  • type
count → arrayrefcreate a new array of primitives of length count and component type identified by type
Type Descriptor alias
booleanZ
charC
floatF
doubleD
byteB
shortS
intI
longJ
multianewarray
  • desc
  • dims
count1, [count2,...] → arrayrefcreate a new array of dims dimensions of type identified by desc
arraylengtharrayref → lengthget the length of an array
aaloadarrayref, index → valueload a reference from an array
aastorearrayref, index, value →store a reference into an array
baloadarrayref, index → valueload a byte or boolean from an array
bastorearrayref, index, value →store a byte or boolean into an array
caloadarrayref, index → valueload a char from an array
castorearrayref, index, value →store a char into an array
daloadarrayref, index → valueload a double from an array
dastorearrayref, index, value →store a double into an array
faloadarrayref, index → valueload a float from an array
fastorearrayref, index, value →store a float in an array
ialoadarrayref, index → valueload an int from an array
iastorearrayref, index, value →store an int into an array
laloadarrayref, index → valueload a long from an array
lastorearrayref, index, value →store a long to an array
saloadarrayref, index → valueload short from an array
sastorearrayref, index, value →store short to array

Variables

OpcodeStack: [before]→[after]Description
iload
  • var
→ valueload an int value from a local variable var
lload
  • var
→ valueload a long value from a local variable var
fload
  • var
→ valueload a float value from a local variable var
dload
  • var
→ valueload a double value from a local variable var
aload
  • var
→ objectrefload 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.

Stack Math

OpcodeStack: [before]→[after]Description
daddvalue1, value2 → resultadd two double values value2 + value1
ddivvalue1, value2 → resultdivide two double values value2 / value1
dmulvalue1, value2 → resultmultiply two double values value2 * value1
dremvalue1, value2 → resultget the remainder from a division between two double values (value2 - ((value1 / value2) * value2))
dsubvalue1, value2 → resultsubtract a double from another value2 - value1
faddvalue1, value2 → resultadd two float values value2 + value1
fdivvalue1, value2 → resultdivide two float values value2 / value1
fmulvalue1, value2 → resultmultiply two float values value2 * value1
fremvalue1, value2 → resultget the remainder from a division between two float values (value2 - ((value1 / value2) * value2))
fsubvalue1, value2 → resultsubtract two float values value2 - value1
iaddvalue1, value2 → resultadd two int values value2 + value1
idivvalue1, value2 → resultdivide two int values value2 / value1
imulvalue1, value2 → resultmultiply two int values value2 * value1
iremvalue1, value2 → resultlogical int remainder (value2 - ((value1 / value2) * value2))
isubvalue1, value2 → resultint subtract value2 - value1
iandvalue1, value2 → resultperform a bitwise AND on two int values value2 & value1
iorvalue1, value2 → resultbitwise int OR `value2
ixorvalue1, value2 → resultint xor value2 ^ value1
ishlvalue1, value2 → resultint shift left value2 << value1
ishrvalue1, value2 → resultint arithmetic shift right value2 >> value1
iushrvalue1, value2 → resultint logical shift right value2 >>> value1
laddvalue1, value2 → resultadd two long values value2 + value1
ldivvalue1, value2 → resultdivide two long values value2 / value1
lmulvalue1, value2 → resultmultiply two long values value2 * value1
lremvalue1, value2 → resultremainder of division of two long values (value2 - ((value1 / value2) * value2))
lsubvalue1, value2 → resultsubtract two long values value2 - value1
lshlvalue1, value2 → resultbitwise shift left of a long value1 by int value2 positions value2 << value1
lshrvalue1, value2 → resultbitwise shift right of a long value1 by int value2 positions value2 >> value1
lushrvalue1, value2 → resultbitwise shift right of a long value1 by int value2 positions, unsigned value2 >>> value1
landvalue1, value2 → resultbitwise AND of two long values value2 ^ value1
lorvalue1, value2 → resultbitwise OR of two long values `value2
lxorvalue1, value2 → resultbitwise XOR of two long values value2 ^ value1
dnegvalue → resultnegate a double -value
fnegvalue → resultnegate a float -value
inegvalue → resultnegate int -value
lnegvalue → resultnegate a long -value
dcmpgvalue1, value2 → resultcompare two double values
ComparisonValue
value1==NaN or
value2==NaN
1
value1 > value21
value1==value20
value1 < value2-1
dcmplvalue1, value2 → resultcompare two double values
ComparisonValue
value1==NaN or
value2==NaN
-1
value1 > value21
value1==value20
value1 < value2-1
fcmpgvalue1, value2 → resultcompare two float values
ComparisonValue
value1==NaN or
value2==NaN
1
value1 > value21
value1==value20
value1 < value2-1
fcmplvalue1, value2 → resultcompare two float values
ComparisonValue
value1==NaN or
value2==NaN
-1
value1 > value21
value1==value20
value1 < value2-1
lcmpvalue1, value2 → resultcompare two long values
ComparisonValue
value1==value20
value1 > value21
value1 < value2-1

Stack Manipulation

OpcodeStack: [before]→[after]Description
dupvalue → value, valueduplicate the value on top of the stack
dup_x1value2, value1 → value1, value2, value1insert a copy of the top value into the stack two values from the top. value1 and value2 must not be of the type double or long.
dup_x2value3, value2, value1 → value1, value3, value2, value1insert 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
dup2{value2, value1} → {value2, value1}, {value2, value1}duplicate top two stack words (two values, if value1 is not double nor long; a single value, if value1 is double or long)
dup2_x1value3, {value2, value1} → {value2, value1}, value3, {value2, value1}duplicate two words and insert beneath third word (see explanation above)
dup2_x2{value4, value3}, {value2, value1} → {value2, value1}, {value4, value3}, {value2, value1}duplicate two words and insert beneath fourth word
popvalue →discard the top value on the stack
pop2{value2, value1} →discard the top two values on the stack (or one value, if it is a double or long)
swapvalue2, value1 → value1, value2swaps two top words on the stack (note that value1 and value2 must not be double or long)

Control Flow

OpcodeStack: [before]→[after]Description
goto
  • label
[no change]jump to label
if_acmpeq
  • label
value1, value2 →if references value1 == value2, jump to label
if_acmpne
  • label
value1, value2 →if references value1 != value2, jump to label
if_icmpeq
  • label
value1, value2 →if ints value1 == value2, jump to label
if_icmpge
  • label
value1, value2 →if ints value1 >= value2, jump to label
if_icmpgt
  • label
value1, value2 →if ints value1 > value2, jump to label
if_icmple
  • label
value1, value2 →if ints value1 <= value2, jump to label
if_icmplt
  • label
value1, value2 →if ints value1 < value2, jump to label
if_icmpne
  • label
value1, value2 →if ints value1 != value2, jump to label
ifeq
  • label
value →if value == 0, jump to label
ifge
  • label
value →if value >= 0, jump to label
ifgt
  • label
value →if value > 0, jump to label
ifle
  • label
value →if value <= 0, jump to label
iflt
  • label
value →if value < 0, jump to label
ifne
  • label
value →if value != 0, jump to label
ifnonnull
  • label
value →if value != null, jump to label
ifnull
  • label
value →if value == null, jump to label
lookupswitch
  • pair[...]
    • key
    • label
key →jump to the label associated with the given key, or if no such entry in the table exists jump to the default label
tableswitch
  • min
  • max
  • cases
  • default
index →jump to the label associated with cases[min-index], or if the computed index of min-index is out of bounds jump to the default label
athrowobjectref → [empty], objectrefthrows an error or exception (notice that the rest of the stack is cleared, leaving only a reference to the Throwable)
jsr
  • label
value → addressjump to label while also pushing the current code address to the stack (Generally this is immediately stored in a variable at the destination)
ret
  • var
[no change]jump to the code offset stored in the variable var

NOTE: jsr and ret are deprecated instructions and are only present in classes from Java 7 or earlier. They cannot be used in Java 8 or above.

Fields

OpcodeStack: [before]→[after]Description
getfield
  • owner
  • name
  • desc
objectref → valueget an instance field defined by the owner class and the field's name and desc
getstatic
  • owner
  • name
  • desc
→ valueget a static field defined by the owner class and the field's name and desc
putfield
  • owner
  • name
  • desc
objectref, value →set an instance field defined by the owner class and the field's name and desc
putstatic
  • owner
  • name
  • desc
value →set a static field defined by the owner class and the field's name and desc

Method Calls

OpcodeStack: [before]→[after]Description
invokeinterface
  • owner
  • name
  • desc
objectref, [arg1, arg2, ...] → resultinvokes 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, ...] → resultinvokes 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, ...] → resultinvokes 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, ...] → resultinvokes 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, ...] → resultinvokes 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, ...] → resultinvokes 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, ...] → resultinvokes 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).

Dynamic Methods Calls

OpcodeStack: [before]→[after]Description
invokedynamic
  • definition
    • name, desc
  • bootstrap handle
    • owner, name, desc
  • bootstrap arguments[]
[arg1, arg2 ...] → resultinvokes a dynamic method and puts the result on the stack (might be void). The callsite handles the dynamic invocation.

NOTE: Before Java 9 - JEP 280 String 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.

Type Conversion

OpcodeStack: [before]→[after]Description
d2fvalue → resultconvert: double to float
d2ivalue → resultconvert: double to int
d2lvalue → resultconvert: double to long
f2dvalue → resultconvert: float to double
f2ivalue → resultconvert: float to int
f2lvalue → resultconvert: float to long
i2bvalue → resultconvert: int to byte
i2cvalue → resultconvert: int to char
i2dvalue → resultconvert: int to double
i2fvalue → resultconvert: int to float
i2lvalue → resultconvert: int to long
i2svalue → resultconvert: int to short
l2dvalue → resultconvert: long to double
l2fvalue → resultconvert: long to float
l2ivalue → resultconvert: long to int
checkcast
  • type
objectref → objectrefchecks whether an objectref is of a certain specified type
instanceof
  • type
objectref → resultdetermines if an object objectref is of a given type

An alternative view for the primitive-to-primitive conversions:

From → Tointlongfloatdoublebytecharshort
int=i2li2fi2di2bi2ci2s
longl2i=l2fl2d
floatf2if2l=f2d
doubled2id2ld2f=

Returns

OpcodeStack: [before]→[after]Description
areturnobjectref → [empty]return a reference
dreturnvalue → [empty]return a double
freturnvalue → [empty]return a float
ireturnvalue → [empty]return an int
lreturnvalue → [empty]return a long
return→ [empty]return void (nothing)

Miscellaneous

OpcodeStack: [before]→[after]Description
monitorenterobjectref →enter monitor for object ("grab the lock" – start of synchronized(objectref) section)
monitorexitobjectref →exit monitor for object ("release the lock" – end of synchronized(objectref) section)
nop[No change]do nothing
line
  • line
[No change]marker that represents a LineNumberTable entry for the given line, beginning at the first label preceding the marker
label:[No change]marker in bytecode for the beginning of a block of instructions; referenced by jump and switch instructions