Java bytecode: Difference between revisions

Content deleted Content added
m Fixed citation needed (reference to reserved opcodes)
per extensive discussion
Line 1:
'''Java bytecode''' is the form of instructions that the [[Java virtual machine]] executes. Each [[bytecode]] instruction or opcode is one byte in length, however not all of the possible 256 instructions are used. In fact, [[Sun Microsystems]], the original creators of the [[Java (programming language)|Java programming language]], the [[Java virtual machine]] and other components of the Java Runtime Environment (JRE), have set aside a number of values to be permanently unimplemented.<ref name="reserved_opcodes">[http://java.sun.com/docs/books/jvms/second_edition/html/Instructions.doc.html#60105 VM Spec - Reserved Opcodes]</ref>
{{rewrite}}
 
'''Java bytecode''' is the form of instructions that the [[Java virtual machine]] executes. Each [[bytecode]] instruction or opcode is one byte in length, however not all of the possible 256 instructions are used. In fact, [[Sun Microsystems]], the original creators of the [[Java (programming language)|Java programming language]], the [[Java virtual machine]] and other components of the Java Runtime Environment (JRE), have set aside a number of values to be permanently unimplemented<ref name="reserved_opcodes">[http://java.sun.com/docs/books/jvms/second_edition/html/Instructions.doc.html#60105 VM Spec - Reserved Opcodes]</ref>.
 
== Relation to Java ==
Line 7 ⟶ 5:
A [[Java (programming language)|Java]] programmer does not need to be aware of or understand Java bytecode at all. However, as suggested in the [[IBM]] developerWorks journal, "Understanding bytecode and what bytecode is likely to be generated by a [[Java compiler]] helps the Java programmer in the same way that knowledge of [[assembly Language|assembler]] helps the [[C (programming language)|C]] or [[C++]] programmer."<ref>[http://www-128.ibm.com/developerworks/ibm/library/it-haggar_bytecode/ Understanding bytecode makes you a better programmer]</ref>.
 
== Generating bytecodeGeneration ==
 
The most common language targeting [[Java Virtual Machine]] by producing Java bytecode is Java. Originally only one compiler existed, the [[javac]] compiler from Sun Microsystems, which compiles [[Java source code]] to Java bytecode; but because all the specifications for Java bytecode are now available, other parties have supplied compilers that produce Java bytecode. Examples of other compilers include:
Line 16 ⟶ 14:
 
Some projects provide Java assemblers to enable writing Java bytecode by hand. Assembler code may be also generated by machine, for example by compiler targeting [[Java virtual machine]]. Notable Java assemblers include:
 
* [[Jasmin (Java assembler)|Jasmin]], takes textual descriptions for Java classes, written in a simple assembler-like syntax using Java Virtual Machine instruction set and generates a Java class file <ref>[http://jasmin.sourceforge.net Jasmin Home Page<!-- Bot generated title -->]</ref>
* [[Jamaica (Java assembler)|Jamaica]], a [[Macro (computer science)|macro]] [[assembly language]] for the [[Java virtual machine]]. Java syntax is used for class or interface definition. Method bodies are specified using bytecode instructions. <ref>[http://www.judoscript.org/jamaica.html Jamaica: The Java Virtual Machine (JVM) Macro Assembler<!-- Bot generated title -->]</ref>
 
Others developed compilers for different programming languages targeting Java virtual machine, such as:
 
* [[JGNAT]] and [[AdaMagic|AppletMagic]], compile from the [[Ada programming language]] to Java bytecode
* [[Jython]], a [[scripting language]] based on [[Python (programming language)|Python]]
Line 25:
* [[C to Java byte-code compiler]]s
 
== Bytecode executionExecution ==
 
Java bytecode is designed to be executed in [[Java virtual machine]]. There are several virtual machines available today both free or commercial.
Line 33:
If executing Java bytecode in a Java virtual machine is not desirable, a developer can also compile Java source code or Java bytecode directly to native machine code with tools such as the [[GCJ|GNU Compiler for Java]].
 
==Support for dynamic languages==
== Example ==
{{main|list of JVM languages}}
 
The [[Java Virtual Machine]] has currently no built-in support for [[Type system#Dynamic_typing|dynamically typed languages]], because the existing JVM instruction set is [[Type system#Static typing|statically typed]].<ref>{{cite web
Consider the following Java code.
 
<source lang="java">
outer:
for (int i = 2; i < 1000; i++) {
for (int j = 2; j < i; j++) {
if (i % j == 0)
continue outer;
}
System.out.println (i);
}
</source>
 
A Java compiler might translate the Java code above into byte code as follows, assuming the above was put in a method:
 
<code>
Code:
0: iconst_2
1: istore_1
2: iload_1
3: sipush 1000
6: if_icmpge 44
9: iconst_2
10: istore_2
11: iload_2
12: iload_1
13: if_icmpge 31
16: iload_1
17: iload_2
18: irem # remainder
19: ifne 25
22: goto 38
25: iinc 2, 1
28: goto 11
31: getstatic #84; //Field java/lang/System.out:Ljava/io/PrintStream;
34: iload_1
35: invokevirtual #85; //Method java/io/PrintStream.println:(I)V
38: iinc 1, 1
41: goto 2
44: return
</code>
 
==The Java bytecodes==
<small>''See Sun's Java Virtual Machine Specification<ref>[http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html Sun's Java Virtual Machine Specification]</ref> for more detailed descriptions''</small>
 
{| class="wikitable"
! Mnemonic !! Opcode<br>''(in [[hexadecimal|hex]])'' !! Other bytes !! Stack<br>[before]→[after] !! Description
|-
! colspan="5" | A
|-
| aaload || align="center" | 32 || || arrayref, index → value || loads onto the stack a reference from an array
|-
| aastore || align="center" | 53 || || arrayref, index, value → || stores a reference into an array
|-
| aconst_null || align="center" | 01 || || → null || pushes a ''null'' reference onto the stack
|-
| aload || align="center" | 19 || index || → objectref || loads a reference onto the stack from a local variable ''#index''
|-
| aload_0 || align="center" | 2a || || → objectref || loads a reference onto the stack from local variable 0
|-
| aload_1 || align="center" | 2b || || → objectref || loads a reference onto the stack from local variable 1
|-
| aload_2 || align="center" | 2c || || → objectref || loads a reference onto the stack from local variable 2
|-
| aload_3 || align="center" | 2d || || → objectref || loads a reference onto the stack from local variable 3
|-
| anewarray || align="center" | bd || indexbyte1, indexbyte2 || count → arrayref || creates a new array of references of length ''count'' and component type identified by the class reference ''index'' (''indexbyte1 &lt;&lt; 8 + indexbyte2'') in the constant pool
|-
| areturn || align="center" | b0 || || objectref → [empty] || returns a reference from a method
|-
| arraylength || align="center" | be || || arrayref → length || gets the length of an array
|-
| astore || align="center" | 3a || index || objectref → || stores a reference into a local variable ''#index''
|-
| astore_0 || align="center" | 4b || || objectref → || stores a reference into local variable 0
|-
| astore_1 || align="center" | 4c || || objectref → || stores a reference into local variable 1
|-
| astore_2 || align="center" | 4d || || objectref → || stores a reference into local variable 2
|-
| astore_3 || align="center" | 4e || || objectref → || stores a reference into local variable 3
|-
| athrow || align="center" | bf || || objectref → [empty], objectref || throws an error or exception (notice that the rest of the stack is cleared, leaving only a reference to the Throwable)
|-
! colspan="5" | B
|-
| baload || align="center" | 33 || || arrayref, index → value || loads a byte or Boolean value from an array
|-
| bastore || align="center" | 54 || || arrayref, index, value → || stores a byte or Boolean value into an array
|-
| bipush || align="center" | 10 || byte || → value || pushes a ''byte'' onto the stack as an integer ''value''
|-
! colspan="5" | C
|-
| caload || align="center" | 34 || || arrayref, index → value || loads a char from an array
|-
| castore || align="center" | 55 || || arrayref, index, value → || stores a char into an array
|-
| checkcast || align="center" | c0 || indexbyte1, indexbyte2 || objectref → objectref || checks whether an ''objectref'' is of a certain type, the class reference of which is in the constant pool at ''index'' (''indexbyte1 &lt;&lt; 8 + indexbyte2'')
|-
! colspan="5" | D
|-
| d2f || align="center" | 90 || || value → result || converts a double to a float
|-
| d2i || align="center" | 8e || || value → result || converts a double to an int
|-
| d2l || align="center" | 8f || || value → result || converts a double to a long
|-
| dadd || align="center" | 63 || || value1, value2 → result || adds two doubles
|-
| daload || align="center" | 31 || || arrayref, index → value || loads a double from an array
|-
| dastore || align="center" | 52 || || arrayref, index, value → || stores a double into an array
|-
| dcmpg || align="center" | 98 || || value1, value2 → result || compares two doubles
|-
| dcmpl || align="center" | 97 || || value1, value2 → result || compares two doubles
|-
| dconst_0 || align="center" | 0e || || → 0.0 || pushes the constant ''0.0'' onto the stack
|-
| dconst_1 || align="center" | 0f || || → 1.0 || pushes the constant ''1.0'' onto the stack
|-
| ddiv || align="center" | 6f || || value1, value2 → result || divides two doubles
|-
| dload || align="center" | 18 || index || → value || loads a double ''value'' from a local variable ''#index''
|-
| dload_0 || align="center" | 26 || || → value || loads a double from local variable 0
|-
| dload_1 || align="center" | 27 || || → value || loads a double from local variable 1
|-
| dload_2 || align="center" | 28 || || → value || loads a double from local variable 2
|-
| dload_3 || align="center" | 29 || || → value || loads a double from local variable 3
|-
| dmul || align="center" | 6b || || value1, value2 → result || multiplies two doubles
|-
| dneg || align="center" | 77 || || value → result || negates a double
|-
| drem || align="center" | 73 || || value1, value2 → result || gets the remainder from a division between two doubles
|-
| dreturn || align="center" | af || || value → [empty] || returns a double from a method
|-
| dstore || align="center" | 39 || index || value → || stores a double ''value'' into a local variable ''#index''
|-
| dstore_0 || align="center" | 47 || || value → || stores a double into local variable 0
|-
| dstore_1 || align="center" | 48 || || value → || stores a double into local variable 1
|-
| dstore_2 || align="center" | 49 || || value → || stores a double into local variable 2
|-
| dstore_3 || align="center" | 4a || || value → || stores a double into local variable 3
|-
| dsub || align="center" | 67 || || value1, value2 → result || subtracts a double from another
|-
| dup || align="center" | 59 || || value → value, value || duplicates the value on top of the stack
|-
| dup_x1 || align="center" | 5a || || value2, value1 → value1, value2, value1 || inserts a copy of the top value into the stack two values from the top
|-
| dup_x2 || align="center" | 5b || || value3, value2, value1 → value1, value3, value2, value1 || inserts 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 || align="center" | 5c || || {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_x1 || align="center" | 5d || || value3, {value2, value1} → {value2, value1}, value3, {value2, value1} || duplicate two words and insert beneath third word (see explanation above)
|-
| dup2_x2 || align="center" | 5e || || {value4, value3}, {value2, value1} → {value2, value1}, {value4, value3}, {value2, value1} || duplicate two words and insert beneath fourth word
|-
! colspan="5" | F
|-
| f2d || align="center" | 8d || || value → result || converts a float to a double
|-
| f2i || align="center" | 8b || || value → result || converts a float to an int
|-
| f2l || align="center" | 8c || || value → result || converts a float to a long
|-
| fadd || align="center" | 62 || || value1, value2 → result || adds two floats
|-
| faload || align="center" | 30 || || arrayref, index → value || loads a float from an array
|-
| fastore || align="center" | 51 || || arreyref, index, value → || stores a float in an array
|-
| fcmpg || align="center" | 96 || || value1, value2 → result || compares two floats
|-
| fcmpl || align="center" | 95 || || value1, value2 → result || compares two floats
|-
| fconst_0 || align="center" | 0b || || → 0.0f || pushes ''0.0f'' on the stack
|-
| fconst_1 || align="center" | 0c || || → 1.0f || pushes ''1.0f'' on the stack
|-
| fconst_2 || align="center" | 0d || || → 2.0f || pushes ''2.0f'' on the stack
|-
| fdiv || align="center" | 6e || || value1, value2 → result || divides two floats
|-
| fload || align="center" | 17 || index || → value || loads a float ''value'' from a local variable ''#index''
|-
| fload_0 || align="center" | 22 || || → value || loads a float ''value'' from local variable 0
|-
| fload_1 || align="center" | 23 || || → value || loads a float ''value'' from local variable 1
|-
| fload_2 || align="center" | 24 || || → value || loads a float ''value'' from local variable 2
|-
| fload_3 || align="center" | 25 || || → value || loads a float ''value'' from local variable 3
|-
| fmul || align="center" | 6a || || value1, value2 → result || multiplies two floats
|-
| fneg || align="center" | 76 || || value → result || negates a float
|-
| frem || align="center" | 72 || || value1, value2 → result || gets the remainder from a division between two floats
|-
| freturn || align="center" | ae || || value → [empty] || returns a float from method
|-
| fstore || align="center" | 38 || index || value → || stores a float ''value'' into a local variable ''#index''
|-
| fstore_0 || align="center" | 43 || || value → || stores a float ''value'' into local variable 0
|-
| fstore_1 || align="center" | 44 || || value → || stores a float ''value'' into local variable 1
|-
| fstore_2 || align="center" | 45 || || value → || stores a float ''value'' into local variable 2
|-
| fstore_3 || align="center" | 46 || || value → || stores a float ''value'' into local variable 3
|-
| fsub || align="center" | 66 || || value1, value2 → result || subtracts two floats
|-
! colspan="5" | G
|-
| getfield || align="center" | b4 || index1, index2 || objectref → value || gets a field ''value'' of an object ''objectref'', where the field is identified by field reference in the constant pool ''index'' (''index1 &lt;&lt; 8 + index2'')
|-
| getstatic || align="center" | b2 || index1, index2 || → value || gets a static field ''value'' of a class, where the field is identified by field reference in the constant pool ''index'' (''index1 &lt;&lt; 8 + index2'')
|-
| goto || align="center" | a7 || branchbyte1, branchbyte2 || [no change] || goes to another instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| goto_w || align="center" | c8 || branchbyte1, branchbyte2, branchbyte3, branchbyte4 || [no change] || goes to another instruction at ''branchoffset'' (signed int constructed from unsigned bytes ''branchbyte1 &lt;&lt; 24 + ''branchbyte2 &lt;&lt; 16 + ''branchbyte3 &lt;&lt; 8 + branchbyte4'')
|-
! colspan="5" | I
|-
| i2b || align="center" | 91 || || value → result || converts an int into a byte
|-
| i2c || align="center" | 92 || || value → result || converts an int into a character
|-
| i2d || align="center" | 87 || || value → result || converts an int into a double
|-
| i2f || align="center" | 86 || || value → result || converts an int into a float
|-
| i2l || align="center" | 85 || || value → result || converts an int into a long
|-
| i2s || align="center" | 93 || || value → result || converts an int into a short
|-
| iadd || align="center" | 60 || || value1, value2 → result || adds two ints together
|-
| iaload || align="center" | 2e || || arrayref, index → value || loads an int from an array
|-
| iand || align="center" | 7e || || value1, value2 → result || performs a logical and on two integers
|-
| iastore || align="center" | 4f || || arrayref, index, value → || stores an int into an array
|-
| iconst_m1 || align="center" | 02 || || → -1 || loads the int value -1 onto the stack
|-
| iconst_0 || align="center" | 03 || || → 0 || loads the int value 0 onto the stack
|-
| iconst_1 || align="center" | 04 || || → 1 || loads the int value 1 onto the stack
|-
| iconst_2 || align="center" | 05 || || → 2 || loads the int value 2 onto the stack
|-
| iconst_3 || align="center" | 06 || || → 3 || loads the int value 3 onto the stack
|-
| iconst_4 || align="center" | 07 || || → 4 || loads the int value 4 onto the stack
|-
| iconst_5 || align="center" | 08 || || → 5 || loads the int value 5 onto the stack
|-
| idiv || align="center" | 6c || || value1, value2 → result || divides two integers
|-
| if_acmpeq || align="center" | a5 || branchbyte1, branchbyte2 || value1, value2 → || if references are equal, branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| if_acmpne || align="center" | a6 || branchbyte1, branchbyte2 || value1, value2 → || if references are not equal, branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| if_icmpeq || align="center" | 9f || branchbyte1, branchbyte2 || value1, value2 → || if ints are equal, branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| if_icmpne || align="center" | a0 || branchbyte1, branchbyte2 || value1, value2 → || if ints are not equal, branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| if_icmplt || align="center" | a1 || branchbyte1, branchbyte2 || value1, value2 → || if ''value1'' is less than ''value2'', branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| if_icmpge || align="center" | a2 || branchbyte1, branchbyte2 || value1, value2 → || if ''value1'' is greater than or equal to ''value2'', branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| if_icmpgt || align="center" | a3 || branchbyte1, branchbyte2 || value1, value2 → || if ''value1'' is greater than ''value2'', branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| if_icmple || align="center" | a4 || branchbyte1, branchbyte2 || value1, value2 → || if ''value1'' is less than or equal to ''value2'', branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| ifeq || align="center" | 99 || branchbyte1, branchbyte2 || value → || if ''value'' is 0, branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| ifne || align="center" | 9a || branchbyte1, branchbyte2 || value → || if ''value'' is not 0, branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| iflt || align="center" | 9b || branchbyte1, branchbyte2 || value → || if ''value'' is less than 0, branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| ifge || align="center" | 9c || branchbyte1, branchbyte2 || value → || if ''value'' is greater than or equal to 0, branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| ifgt || align="center" | 9d || branchbyte1, branchbyte2 || value → || if ''value'' is greater than 0, branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| ifle || align="center" | 9e || branchbyte1, branchbyte2 || value → || if ''value'' is less than or equal to 0, branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| ifnonnull || align="center" | c7 || branchbyte1, branchbyte2 || value → || if ''value'' is not null, branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| ifnull || align="center" | c6 || branchbyte1, branchbyte2 || value → || if ''value'' is null, branch to instruction at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'')
|-
| iinc || align="center" | 84 || index, const || [No change] || increment local variable ''#index'' by signed byte ''const''
|-
| iload || align="center" | 15 || index || → value || loads an int ''value'' from a variable ''#index''
|-
| iload_0 || align="center" | 1a || || → value || loads an int ''value'' from variable 0
|-
| iload_1 || align="center" | 1b || || → value || loads an int ''value'' from variable 1
|-
| iload_2 || align="center" | 1c || || → value || loads an int ''value'' from variable 2
|-
| iload_3 || align="center" | 1d || || → value || loads an int ''value'' from variable 3
|-
| imul || align="center" | 68 || || value1, value2 → result || multiply two integers
|-
| ineg || align="center" | 74 || || value → result || negate int
|-
| instanceof || align="center" | c1 || indexbyte1, indexbyte2 || objectref → result || determines if an object ''objectref'' is of a given type, identified by class reference ''index'' in constant pool (''indexbyte1 &lt;&lt; 8 + indexbyte2'')
|-
| invokeinterface || align="center" | b9 || indexbyte1, indexbyte2, count, 0 || objectref, [arg1, arg2, ...] → || invokes an interface method on object ''objectref'', where the interface method is identified by method reference ''index'' in constant pool (''indexbyte1 &lt;&lt; 8 + indexbyte2'') and ''count'' is the number of arguments to pop from the stack frame including the object on which the method is being called and must always be greater than or equal to 1
|-
| invokespecial || align="center" | b7 || indexbyte1, indexbyte2 || objectref, [arg1, arg2, ...] → || invoke instance method on object ''objectref'' requiring special handling (instance initialization method, a private method, or a superclass method), where the method is identified by method reference ''index'' in constant pool (''indexbyte1 &lt;&lt; 8 + indexbyte2'')
|-
| invokestatic || align="center" | b8 || indexbyte1, indexbyte2 || [arg1, arg2, ...] → || invoke a static method, where the method is identified by method reference ''index'' in constant pool (''indexbyte1 &lt;&lt; 8 + indexbyte2'')
|-
| invokevirtual || align="center" | b6 || indexbyte1, indexbyte2 || objectref, [arg1, arg2, ...] → || invoke virtual method on object ''objectref'', where the method is identified by method reference ''index'' in constant pool (''indexbyte1 &lt;&lt; 8 + indexbyte2'')
|-
| ior || align="center" | 80 || || value1, value2 → result || logical int or
|-
| irem || align="center" | 70 || || value1, value2 → result || logical int remainder
|-
| ireturn || align="center" | ac || || value → [empty] || returns an integer from a method
|-
| ishl || align="center" | 78 || || value1, value2 → result || int shift left
|-
| ishr || align="center" | 7a || || value1, value2 → result || int shift right
|-
| istore || align="center" | 36 || index || value → || store int ''value'' into variable ''#index''
|-
| istore_0 || align="center" | 3b || || value → || store int ''value'' into variable 0
|-
| istore_1 || align="center" | 3c || || value → || store int ''value'' into variable 1
|-
| istore_2 || align="center" | 3d || || value → || store int ''value'' into variable 2
|-
| istore_3 || align="center" | 3e || || value → || store int ''value'' into variable 3
|-
| isub || align="center" | 64 || || value1, value2 → result || int subtract
|-
| iushr || align="center" | 7c || || value1, value2 → result || int shift right
|-
| ixor || align="center" | 82 || || value1, value2 → result || int xor
|-
! colspan="5" | J
|-
| jsr || align="center" | a8 || branchbyte1, branchbyte2 || → address || jump to subroutine at ''branchoffset'' (signed short constructed from unsigned bytes ''branchbyte1 &lt;&lt; 8 + branchbyte2'') and place the return address on the stack
|-
| jsr_w || align="center" | c9 || branchbyte1, branchbyte2, branchbyte3, branchbyte4 || → address || jump to subroutine at ''branchoffset'' (signed int constructed from unsigned bytes ''branchbyte1 &lt;&lt; 24 + branchbyte2 &lt;&lt; 16 + branchbyte3 &lt;&lt; 8 + branchbyte4'') and place the return address on the stack
|-
! colspan="5" | L
|-
| l2d || align="center" | 8a || || value → result || converts a long to a double
|-
| l2f || align="center" | 89 || || value → result || converts a long to a float
|-
| l2i || align="center" | 88 || || value → result || converts a long to an int
|-
| ladd || align="center" | 61 || || value1, value2 → result || add two longs
|-
| laload || align="center" | 2f || || arrayref, index → value || load a long from an array
|-
| land || align="center" | 7f || || value1, value2 → result || bitwise and of two longs
|-
| lastore || align="center" | 50 || || arrayref, index, value → || store a long to an array
|-
| lcmp || align="center" | 94 || || value1, value2 → result || compares two longs values
|-
| lconst_0 || align="center" | 09 || || → 0L || pushes the long 0 onto the stack
|-
| lconst_1 || align="center" | 0a || || → 1L || pushes the long 1 onto the stack
|-
| ldc || align="center" | 12 || index || → value || pushes a constant ''#index'' from a constant pool (String, int, float or class type) onto the stack
|-
| ldc_w || align="center" | 13 || indexbyte1, indexbyte2 || → value || pushes a constant ''#index'' from a constant pool (String, int, float or class type) onto the stack (wide ''index'' is constructed as ''indexbyte1 &lt;&lt; 8 + indexbyte2'')
|-
| ldc2_w || align="center" | 14 || indexbyte1, indexbyte2 || → value || pushes a constant ''#index'' from a constant pool (double or long) onto the stack (wide ''index'' is constructed as ''indexbyte1 &lt;&lt; 8 + indexbyte2'')
|-
| ldiv || align="center" | 6d || || value1, value2 → result || divide two longs
|-
| lload || align="center" | 16 || index || → value || load a long value from a local variable ''#index''
|-
| lload_0 || align="center" | 1e || || → value || load a long value from a local variable 0
|-
| lload_1 || align="center" | 1f || || → value || load a long value from a local variable 1
|-
| lload_2 || align="center" | 20 || || → value || load a long value from a local variable 2
|-
| lload_3 || align="center" | 21 || || → value || load a long value from a local variable 3
|-
| lmul || align="center" | 69 || || value1, value2 → result || multiplies two longs
|-
| lneg || align="center" | 75 || || value → result || negates a long
|-
| lookupswitch || align="center" | ab || &lt;0-3 bytes padding&gt;, defaultbyte1, defaultbyte2, defaultbyte3, defaultbyte4, npairs1, npairs2, npairs3, npairs4, match-offset pairs... || key → || a target address is looked up from a table using a key and execution continues from the instruction at that address
|-
| lor || align="center" | 81 || || value1, value2 → result || bitwise or of two longs
|-
| lrem || align="center" | 71 || || value1, value2 → result || remainder of division of two longs
|-
| lreturn || align="center" | ad || || value → [empty] || returns a long value
|-
| lshl || align="center" | 79 || || value1, value2 → result || bitwise shift left of a long ''value1'' by ''value2'' positions
|-
| lshr || align="center" | 7b || || value1, value2 → result || bitwise shift right of a long ''value1'' by ''value2'' positions
|-
| lstore || align="center" | 37 || index || value → || store a long ''value'' in a local variable ''#index''
|-
| lstore_0 || align="center" | 3f || || value → || store a long ''value'' in a local variable 0
|-
| lstore_1 || align="center" | 40 || || value → || store a long ''value'' in a local variable 1
|-
| lstore_2 || align="center" | 41 || || value → || store a long ''value'' in a local variable 2
|-
| lstore_3 || align="center" | 42 || || value → || store a long ''value'' in a local variable 3
|-
| lsub || align="center" | 65 || || value1, value2 → result || subtract two longs
|-
| lushr || align="center" | 7d || || value1, value2 → result || bitwise shift right of a long ''value1'' by ''value2'' positions, unsigned
|-
| lxor || align="center" | 83 || || value1, value2 → result || bitwise exclusive or of two longs
|-
! colspan="5" | M
|-
| monitorenter || align="center" | c2 || || objectref → || enter monitor for object ("grab the lock" - start of synchronized() section)
|-
| monitorexit || align="center" | c3 || || objectref → || exit monitor for object ("release the lock" - end of synchronized() section)
|-
| multianewarray || align="center" | c5 || indexbyte1, indexbyte2, dimensions || count1, [count2,...] → arrayref || create a new array of ''dimensions'' dimensions with elements of type identified by class reference in constant pool ''index'' (''indexbyte1 &lt;&lt; 8 + indexbyte2''); the sizes of each dimension is identified by ''count1'', [''count2'', etc]
|-
! colspan="5" | N
|-
| new || align="center" | bb || indexbyte1, indexbyte2 || → objectref || creates new object of type identified by class reference in constant pool ''index'' (''indexbyte1 &lt;&lt; 8 + indexbyte2'')
|-
| newarray || align="center" | bc || atype || count → arrayref || creates new array with ''count'' elements of primitive type identified by ''atype''
|-
| [[nop]] || align="center" | 00 || || [No change] || performs no operation
|-
! colspan="5" | P
|-
| pop || align="center" | 57 || || value → || discards the top value on the stack
|-
| pop2 || align="center" | 58 || || {value2, value1} → || discards the top two values on the stack (or one value, if it is a double or long)
|-
| putfield || align="center" | b5 || indexbyte1, indexbyte2 || objectref, value → || set field to ''value'' in an object ''objectref'', where the field is identified by a field reference ''index'' in constant pool (''indexbyte1 &lt;&lt; 8 + indexbyte2'')
|-
| putstatic || align="center" | b3 || indexbyte1, indexbyte2 || value → || set static field to ''value'' in a class, where the field is identified by a field reference ''index'' in constant pool (''indexbyte1 &lt;&lt; 8 + indexbyte2'')
|-
! colspan="5" | R
|-
| ret || align="center" | a9 || index || [No change] || continue execution from address taken from a local variable ''#index'' (the asymmetry with jsr is intentional)
|-
| return || align="center" | b1 || || → [empty] || return void from method
|-
! colspan="5" | S
|-
| saload || align="center" | 35 || || arrayref, index → value || load short from array
|-
| sastore || align="center" | 56 || || arrayref, index, value → || store short to array
|-
| sipush || align="center" | 11 || byte1, byte2 || → value || pushes a signed integer (''byte1 &lt;&lt; 8 + byte2'') onto the stack
|-
| swap || align="center" | 5f || || value2, value1 → value1, value2 || swaps two top words on the stack (note that value1 and value2 must not be double or long)
|-
! colspan="5" | T
|-
| tableswitch || align="center" | aa || [0-3 bytes padding], defaultbyte1, defaultbyte2, defaultbyte3, defaultbyte4, lowbyte1, lowbyte2, lowbyte3, lowbyte4, highbyte1, highbyte2, highbyte3, highbyte4, jump offsets... || index → || continue execution from an address in the table at offset ''index''
|-
! colspan="5" | W
|-
| wide || align="center" | c4 || opcode, indexbyte1, indexbyte2 <br>or<br> iinc, indexbyte1, indexbyte2, countbyte1, countbyte2 || [same as for corresponding instructions] || execute ''opcode'', where ''opcode'' is either iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore, or ret, but assume the ''index'' is 16 bit; or execute iinc, where the ''index'' is 16 bits and the constant to increment by is a signed 16 bit short
|-
! colspan="5" | Unused
|-
| breakpoint || align="center" | ca || || || reserved for breakpoints in Java debuggers; should not appear in any class file
|-
| impdep1 || align="center" | fe || || || reserved for implementation-dependent operations within debuggers; should not appear in any class file
|-
| impdep2 || align="center" | ff || || || reserved for implementation-dependent operations within debuggers; should not appear in any class file
|-
| ''(no name)'' || align="center" | cb-fd || || || these values are currently unassigned for opcodes and are reserved for future use
|-
| xxxunusedxxx || align="center" | ba || || || this opcode is reserved "for historical reasons"
|}
 
==Support for Dynamic Languages==
{{main|JVM Languages}}
The [[Java Virtual Machine]] has currently no built-in support for [[Type system#Dynamic_typing|dynamically typed languages]], because the existing JVM instruction set is [[Type system#Static typing|statically typed]]<ref>{{cite web
| url=http://headius.blogspot.com/2007/01/invokedynamic-actually-useful.html
| title=InvokeDynamic: Actually Useful?
| date=[[2007-01-03]]
|last=Nutter|first=Charles
| accessdate=2008-01-25}}</ref>.
 
[[Java Community Process|JSR 292]] (''Supporting Dynamically Typed Languages on the JavaTM Platform'') <ref>[http://www.jcp.org/en/jsr/detail?id=292 see JSR 292]</ref> propose to add a new <code>invokedynamic</code> instruction at the JVM level, to allow method invocation relying on dynamic [[Type system#Type checking|type checking]] (instead of the existing statically type-checked <code>invokevirtual</code> instruction). The [[Da Vinci Machine]] is a prototype virtual machine implementation that hosts JVM extensions aimed at supporting dynamic languages.
 
== References ==
{{reflist|2}}
 
== See also ==
Line 552 ⟶ 52:
* [[ARM9E]]
* [[Common Intermediate Language]]
 
== References ==
{{reflist|2}}
 
== External links ==
{{wikibooks|Java Programming|Byte Code|Java bytecode}}
 
* [http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html Sun's Java Virtual Machine Specification]
* [http://www.is-research.de/info/vmlanguages/ Programming Languages for the Java Virtual Machine]
 
{{Java (Sun)}}
{{Expand list|date=August 2008}}
 
{{listdev}}
 
[[Category:Java platform|Bytecodes]]