A method’s bytecode, in its Code
attribute, is a run of instructions. Each is a one-byte opcode followed by its
operands, if it has any. The JVM is a stack machine: most instructions take their
inputs from the operand stack and push their result back. Local variables are numbered
slots, with this and the parameters first. There are 202 instructions, plus
three reserved opcodes that never appear in a class file.
Operands
Operands follow the opcode directly, big-endian, with no alignment except in the two switch instructions. In the tables below:
| Written | Bytes | Meaning |
|---|---|---|
| i1, i2 | 1, 2 | A signed immediate value |
| cp1, cp2 | 1, 2 | An unsigned constant pool index; the explorer shows the entry it names, as javap does: // Method java/lang/Object."<init>":()V |
| loc | 1 | An unsigned local variable index, 0 to 255; wide makes it two bytes |
| br2, br4 | 2, 4 | A signed branch offset, added to the address of the branch’s own opcode |
The stack column shows the values the instruction takes from the top of the stack,
then what it leaves. Values of type long and double take two
places on the stack and two local slots; everything else takes one. Types
boolean, byte, char and short are
int on the stack.
Constants
| Op | Mnemonic | Operands | Stack | Does |
|---|---|---|---|---|
| 00 | nop | Nothing | ||
| 01 | aconst_null | → null | Pushes null | |
| 02 | iconst_m1 | → int | Pushes −1 | |
| 03 | iconst_0 | → int | Pushes 0 | |
| 04 | iconst_1 | → int | Pushes 1 | |
| 05 | iconst_2 | → int | Pushes 2 | |
| 06 | iconst_3 | → int | Pushes 3 | |
| 07 | iconst_4 | → int | Pushes 4 | |
| 08 | iconst_5 | → int | Pushes 5 | |
| 09 | lconst_0 | → long | Pushes 0L | |
| 0A | lconst_1 | → long | Pushes 1L | |
| 0B | fconst_0 | → float | Pushes 0.0f | |
| 0C | fconst_1 | → float | Pushes 1.0f | |
| 0D | fconst_2 | → float | Pushes 2.0f | |
| 0E | dconst_0 | → double | Pushes 0.0 | |
| 0F | dconst_1 | → double | Pushes 1.0 | |
| 10 | bipush | i1 | → int | Pushes the byte, sign-extended |
| 11 | sipush | i2 | → int | Pushes the short, sign-extended |
| 12 | ldc | cp1 | → value | Pushes an Integer, Float or String constant; a Class from 49.0; a MethodHandle or MethodType from 51.0; a Dynamic from 55.0 |
| 13 | ldc_w | cp2 | → value | As ldc, with a two-byte index |
| 14 | ldc2_w | cp2 | → long or double | Pushes a Long or Double constant, or from 55.0 a Dynamic of type long or double |
Loads
| Op | Mnemonic | Operands | Stack | Does |
|---|---|---|---|---|
| 15 | iload | loc | → int | Pushes an int local |
| 16 | lload | loc | → long | Pushes a long from locals loc and loc + 1 |
| 17 | fload | loc | → float | Pushes a float local |
| 18 | dload | loc | → double | Pushes a double from locals loc and loc + 1 |
| 19 | aload | loc | → ref | Pushes a reference local |
| 1A | iload_0 | → int | Pushes int local 0 | |
| 1B | iload_1 | → int | Pushes int local 1 | |
| 1C | iload_2 | → int | Pushes int local 2 | |
| 1D | iload_3 | → int | Pushes int local 3 | |
| 1E | lload_0 | → long | Pushes long locals 0 and 1 | |
| 1F | lload_1 | → long | Pushes long locals 1 and 2 | |
| 20 | lload_2 | → long | Pushes long locals 2 and 3 | |
| 21 | lload_3 | → long | Pushes long locals 3 and 4 | |
| 22 | fload_0 | → float | Pushes float local 0 | |
| 23 | fload_1 | → float | Pushes float local 1 | |
| 24 | fload_2 | → float | Pushes float local 2 | |
| 25 | fload_3 | → float | Pushes float local 3 | |
| 26 | dload_0 | → double | Pushes double locals 0 and 1 | |
| 27 | dload_1 | → double | Pushes double locals 1 and 2 | |
| 28 | dload_2 | → double | Pushes double locals 2 and 3 | |
| 29 | dload_3 | → double | Pushes double locals 3 and 4 | |
| 2A | aload_0 | → ref | Pushes reference local 0, which is this in an instance method | |
| 2B | aload_1 | → ref | Pushes reference local 1 | |
| 2C | aload_2 | → ref | Pushes reference local 2 | |
| 2D | aload_3 | → ref | Pushes reference local 3 | |
| 2E | iaload | array, index → int | Loads from an int[] | |
| 2F | laload | array, index → long | Loads from a long[] | |
| 30 | faload | array, index → float | Loads from a float[] | |
| 31 | daload | array, index → double | Loads from a double[] | |
| 32 | aaload | array, index → ref | Loads from an array of references | |
| 33 | baload | array, index → int | Loads from a byte[] (sign-extended) or boolean[] | |
| 34 | caload | array, index → int | Loads from a char[], zero-extended | |
| 35 | saload | array, index → int | Loads from a short[], sign-extended |
Every array instruction throws NullPointerException for a null array and
ArrayIndexOutOfBoundsException for an index outside it.
Stores
| Op | Mnemonic | Operands | Stack | Does |
|---|---|---|---|---|
| 36 | istore | loc | int → | Stores into an int local |
| 37 | lstore | loc | long → | Stores into locals loc and loc + 1 |
| 38 | fstore | loc | float → | Stores into a float local |
| 39 | dstore | loc | double → | Stores into locals loc and loc + 1 |
| 3A | astore | loc | ref → | Stores a reference (or a jsr return address) into a local |
| 3B | istore_0 | int → | Stores into local 0 | |
| 3C | istore_1 | int → | Stores into local 1 | |
| 3D | istore_2 | int → | Stores into local 2 | |
| 3E | istore_3 | int → | Stores into local 3 | |
| 3F | lstore_0 | long → | Stores into locals 0 and 1 | |
| 40 | lstore_1 | long → | Stores into locals 1 and 2 | |
| 41 | lstore_2 | long → | Stores into locals 2 and 3 | |
| 42 | lstore_3 | long → | Stores into locals 3 and 4 | |
| 43 | fstore_0 | float → | Stores into local 0 | |
| 44 | fstore_1 | float → | Stores into local 1 | |
| 45 | fstore_2 | float → | Stores into local 2 | |
| 46 | fstore_3 | float → | Stores into local 3 | |
| 47 | dstore_0 | double → | Stores into locals 0 and 1 | |
| 48 | dstore_1 | double → | Stores into locals 1 and 2 | |
| 49 | dstore_2 | double → | Stores into locals 2 and 3 | |
| 4A | dstore_3 | double → | Stores into locals 3 and 4 | |
| 4B | astore_0 | ref → | Stores into local 0 | |
| 4C | astore_1 | ref → | Stores into local 1 | |
| 4D | astore_2 | ref → | Stores into local 2 | |
| 4E | astore_3 | ref → | Stores into local 3 | |
| 4F | iastore | array, index, int → | Stores into an int[] | |
| 50 | lastore | array, index, long → | Stores into a long[] | |
| 51 | fastore | array, index, float → | Stores into a float[] | |
| 52 | dastore | array, index, double → | Stores into a double[] | |
| 53 | aastore | array, index, ref → | Stores into an array of references; throws ArrayStoreException if the value’s type does not fit | |
| 54 | bastore | array, index, int → | Stores into a byte[] (low 8 bits) or boolean[] (lowest bit) | |
| 55 | castore | array, index, int → | Stores into a char[] (low 16 bits) | |
| 56 | sastore | array, index, int → | Stores into a short[] (low 16 bits) |
Stack
These work on stack places regardless of type. A “category 2” value is a
long or double, which fills two places; the forms below are
given for single-place values, and the specification lists which mixes each allows.
| Op | Mnemonic | Operands | Stack | Does |
|---|---|---|---|---|
| 57 | pop | v → | Discards one place | |
| 58 | pop2 | v2, v1 → | Discards two places: two values, or one long or double | |
| 59 | dup | v → v, v | Duplicates the top place | |
| 5A | dup_x1 | v2, v1 → v1, v2, v1 | Duplicates the top and puts it two down | |
| 5B | dup_x2 | v3, v2, v1 → v1, v3, v2, v1 | Duplicates the top and puts it three down | |
| 5C | dup2 | v2, v1 → v2, v1, v2, v1 | Duplicates the top two places (or one long or double) | |
| 5D | dup2_x1 | v3, v2, v1 → v2, v1, v3, v2, v1 | Duplicates the top two and puts them three down | |
| 5E | dup2_x2 | v4, v3, v2, v1 → v2, v1, v4, v3, v2, v1 | Duplicates the top two and puts them four down | |
| 5F | swap | v2, v1 → v1, v2 | Swaps the top two single-place values |
Arithmetic and logic
| Op | Mnemonic | Operands | Stack | Does |
|---|---|---|---|---|
| 60 | iadd | int, int → int | Adds, wrapping on overflow | |
| 61 | ladd | long, long → long | Adds | |
| 62 | fadd | float, float → float | Adds | |
| 63 | dadd | double, double → double | Adds | |
| 64 | isub | int, int → int | Subtracts the top from the one below | |
| 65 | lsub | long, long → long | Subtracts | |
| 66 | fsub | float, float → float | Subtracts | |
| 67 | dsub | double, double → double | Subtracts | |
| 68 | imul | int, int → int | Multiplies | |
| 69 | lmul | long, long → long | Multiplies | |
| 6A | fmul | float, float → float | Multiplies | |
| 6B | dmul | double, double → double | Multiplies | |
| 6C | idiv | int, int → int | Divides, rounding towards zero; throws ArithmeticException on division by zero | |
| 6D | ldiv | long, long → long | Divides; throws ArithmeticException on division by zero | |
| 6E | fdiv | float, float → float | Divides (IEEE 754) | |
| 6F | ddiv | double, double → double | Divides (IEEE 754) | |
| 70 | irem | int, int → int | Remainder, with the sign of the dividend; throws on zero | |
| 71 | lrem | long, long → long | Remainder; throws on zero | |
| 72 | frem | float, float → float | Remainder, truncating as C’s fmod does | |
| 73 | drem | double, double → double | Remainder, as fmod | |
| 74 | ineg | int → int | Negates | |
| 75 | lneg | long → long | Negates | |
| 76 | fneg | float → float | Negates | |
| 77 | dneg | double → double | Negates | |
| 78 | ishl | int, int → int | Shifts left by the low 5 bits of the top value | |
| 79 | lshl | long, int → long | Shifts left by the low 6 bits | |
| 7A | ishr | int, int → int | Shifts right, keeping the sign (>>) | |
| 7B | lshr | long, int → long | Shifts right, keeping the sign | |
| 7C | iushr | int, int → int | Shifts right, filling with zeros (>>>) | |
| 7D | lushr | long, int → long | Shifts right, filling with zeros | |
| 7E | iand | int, int → int | Bitwise and | |
| 7F | land | long, long → long | Bitwise and | |
| 80 | ior | int, int → int | Bitwise or | |
| 81 | lor | long, long → long | Bitwise or | |
| 82 | ixor | int, int → int | Bitwise exclusive or | |
| 83 | lxor | long, long → long | Bitwise exclusive or | |
| 84 | iinc | loc, i1 | Adds a signed byte to an int local, without using the stack |
Conversions
| Op | Mnemonic | Operands | Stack | Does |
|---|---|---|---|---|
| 85 | i2l | int → long | Widens, sign-extending | |
| 86 | i2f | int → float | Converts, rounding to nearest | |
| 87 | i2d | int → double | Converts exactly | |
| 88 | l2i | long → int | Keeps the low 32 bits | |
| 89 | l2f | long → float | Converts, rounding to nearest | |
| 8A | l2d | long → double | Converts, rounding to nearest | |
| 8B | f2i | float → int | Rounds towards zero; NaN gives 0, and values out of range give the nearest limit | |
| 8C | f2l | float → long | As f2i, to long | |
| 8D | f2d | float → double | Widens exactly | |
| 8E | d2i | double → int | As f2i | |
| 8F | d2l | double → long | As f2i, to long | |
| 90 | d2f | double → float | Narrows, rounding to nearest | |
| 91 | i2b | int → int | Truncates to a byte and sign-extends | |
| 92 | i2c | int → int | Truncates to a char and zero-extends | |
| 93 | i2s | int → int | Truncates to a short and sign-extends |
Comparisons
| Op | Mnemonic | Operands | Stack | Does |
|---|---|---|---|---|
| 94 | lcmp | long, long → int | Pushes 1, 0 or −1 as the first is greater, equal or less | |
| 95 | fcmpl | float, float → int | As lcmp; −1 if either is NaN | |
| 96 | fcmpg | float, float → int | As lcmp; 1 if either is NaN | |
| 97 | dcmpl | double, double → int | As fcmpl | |
| 98 | dcmpg | double, double → int | As fcmpg | |
| 99 | ifeq | br2 | int → | Branches if the value is 0 |
| 9A | ifne | br2 | int → | Branches if it is not 0 |
| 9B | iflt | br2 | int → | Branches if it is below 0 |
| 9C | ifge | br2 | int → | Branches if it is 0 or more |
| 9D | ifgt | br2 | int → | Branches if it is above 0 |
| 9E | ifle | br2 | int → | Branches if it is 0 or less |
| 9F | if_icmpeq | br2 | int, int → | Branches if equal |
| A0 | if_icmpne | br2 | int, int → | Branches if not equal |
| A1 | if_icmplt | br2 | int, int → | Branches if the first is less |
| A2 | if_icmpge | br2 | int, int → | Branches if the first is greater or equal |
| A3 | if_icmpgt | br2 | int, int → | Branches if the first is greater |
| A4 | if_icmple | br2 | int, int → | Branches if the first is less or equal |
| A5 | if_acmpeq | br2 | ref, ref → | Branches if the references are the same |
| A6 | if_acmpne | br2 | ref, ref → | Branches if they differ |
Control
| Op | Mnemonic | Operands | Stack | Does |
|---|---|---|---|---|
| A7 | goto | br2 | Branches always | |
| A8 | jsr | br2 | → address | Pushes the address of the next instruction and branches; used by old compilers for finally. Not allowed from 51.0 |
| A9 | ret | loc | Branches to the address held in a local, returning from a jsr. Not allowed from 51.0 | |
| AA | tableswitch | pad, i4 default, i4 low, i4 high, i4 × (high − low + 1) | int → | Branches through a table of offsets indexed by value − low, or to default when the value is outside low to high (see switches) |
| AB | lookupswitch | pad, i4 default, i4 npairs, npairs × (i4 match, i4 offset) | int → | Branches to the offset paired with the value, or to default; the pairs are sorted by match |
| AC | ireturn | int → | Returns an int (or boolean, byte, char, short) | |
| AD | lreturn | long → | Returns a long | |
| AE | freturn | float → | Returns a float | |
| AF | dreturn | double → | Returns a double | |
| B0 | areturn | ref → | Returns a reference | |
| B1 | return | Returns from a void method |
Objects, fields and calls
| Op | Mnemonic | Operands | Stack | Does |
|---|---|---|---|---|
| B2 | getstatic | cp2 Fieldref | → value | Pushes a static field, initialising its class first if need be |
| B3 | putstatic | cp2 Fieldref | value → | Sets a static field |
| B4 | getfield | cp2 Fieldref | object → value | Pushes an instance field |
| B5 | putfield | cp2 Fieldref | object, value → | Sets an instance field |
| B6 | invokevirtual | cp2 Methodref | object, args → [result] | Calls an instance method, chosen by the object’s class |
| B7 | invokespecial | cp2 Methodref, or InterfaceMethodref from 52.0 | object, args → [result] | Calls a method without dispatch: a constructor, a private method or a superclass’s method |
| B8 | invokestatic | cp2 Methodref, or InterfaceMethodref from 52.0 | args → [result] | Calls a static method |
| B9 | invokeinterface | cp2 InterfaceMethodref, u1 count, u1 0 | object, args → [result] | Calls an interface method. count is the number of argument places including the object; the last byte is always 0 |
| BA | invokedynamic | cp2 InvokeDynamic, u1 0, u1 0 | args → [result] | Calls the target of a call site linked by a bootstrap method. From 51.0 |
| BB | new | cp2 Class | → object | Makes an object whose constructor has not run yet; invokespecial <init> follows |
| BC | newarray | u1 atype | count → array | Makes an array of a primitive type (see atype) |
| BD | anewarray | cp2 Class | count → array | Makes an array of references of the class |
| BE | arraylength | array → int | Pushes an array’s length | |
| BF | athrow | object → | Throws the exception | |
| C0 | checkcast | cp2 Class | object → object | Throws ClassCastException unless the object is null or of the type |
| C1 | instanceof | cp2 Class | object → int | Pushes 1 if the object is of the type, 0 if not or if it is null |
| C2 | monitorenter | object → | Takes the object’s monitor, as at the start of a synchronized block | |
| C3 | monitorexit | object → | Releases the monitor |
The arguments of a call are pushed in order, then taken off together; a
long or double argument takes two places. The result, if the
descriptor’s return type is not V, is pushed.
Extended
| Op | Mnemonic | Operands | Stack | Does |
|---|---|---|---|---|
| C4 | wide | opcode, u2 index (and i2 for iinc) | as the opcode | Gives the next instruction a two-byte local index (see wide) |
| C5 | multianewarray | cp2 Class, u1 dimensions | count1 … countN → array | Makes a multi-dimensional array; dimensions is at least 1 and no more than the array type has |
| C6 | ifnull | br2 | ref → | Branches if the reference is null |
| C7 | ifnonnull | br2 | ref → | Branches if it is not null |
| C8 | goto_w | br4 | Branches always, with a four-byte offset | |
| C9 | jsr_w | br4 | → address | As jsr, with a four-byte offset. Not allowed from 51.0 |
Reserved
| Op | Mnemonic | Does |
|---|---|---|
| CA | breakpoint | Reserved for debuggers to set breakpoints; never in a class file |
| FE | impdep1 | Reserved for the JVM’s own use; never in a class file |
| FF | impdep2 | Reserved for the JVM’s own use; never in a class file |
Opcodes CB to FD are not assigned. The explorer turns down code that holds one of them, or CA, FE or FF; when it shows such a file anyway, the rest of the method is shown as unreadable bytes.
Switches and padding
tableswitch and lookupswitch are the only instructions with
alignment. After the opcode come 0 to 3 zero bytes, so that the first four-byte operand
starts at a multiple of 4 from the start of the code (not of the file). The offsets in
the table are relative to the switch’s own opcode.
- A switch at pc 2 has one byte of padding (pc 3), and its default starts at pc 4.
- A switch at pc 3 has no padding: its default starts at pc 4.
- A switch at pc 4 has three bytes of padding, and its default starts at pc 8.
javac picks tableswitch when the case values are dense and
lookupswitch when they are sparse. Switches on strings and enums compile
to these too, after a hash or ordinal lookup; pattern-matching switches use
invokedynamic first. The source side is on the
Java switch page.
wide
wide is followed by another opcode and changes its operands:
| Form | Bytes | Layout |
|---|---|---|
wide with iload, lload, fload, dload, aload, istore, lstore, fstore, dstore, astore or ret | 4 | C4, opcode, u2 index |
wide iinc | 6 | C4 84, u2 index, i2 constant |
No other opcode may follow wide, and a branch may not land on the
instruction it modifies.
newarray types
| atype | Array |
|---|---|
| 4 | boolean[] |
| 5 | char[] |
| 6 | float[] |
| 7 | double[] |
| 8 | byte[] |
| 9 | short[] |
| 10 | int[] |
| 11 | long[] |
Worked bytes
The constructor of java/util/EmptyStackException (JDK 1.1.4) is five
bytes, 2A B7 00 03 B1:
| pc | Bytes | Instruction | Stack after |
|---|---|---|---|
| 0 | 2A | aload_0 | this |
| 1 | B7 00 03 | invokespecial #3, java/lang/RuntimeException."<init>":()V | empty |
| 4 | B1 | return |
A branch: 9C 00 08 at pc 1 is ifge with offset +8, so it
jumps to pc 9. A backward branch has a negative offset: A7 FF F6 at pc 20
is goto pc 10.