Java bytecode: Difference between revisions

Content deleted Content added
The Java bytecodes: argh argh argh. who is this relevant to, outside people implementing bytecode interpreters?
Removing link(s) to "Byte Code Engineering Library": Removing links to deleted page Byte Code Engineering Library.
 
(314 intermediate revisions by more than 100 users not shown)
Line 1:
{{Short description|Instruction set of the Java virtual machine}}
'''Java bytecode''' is the form of instructions that the [[Java virtual machine]] executes. Each [[bytecode]] instruction is one byte in length (hence the name), thus the number of bytecodes is limited to 256. Not all 256 possible bytecode values 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, have set aside a number of values to be permanently unimplemented.
{{Use dmy dates|date=November 2023}}
{{Use American English|date=November 2023}}
 
'''Java bytecode''' is the instruction set of the [[Java virtual machine]] (JVM), the language to which [[Java (programming language)|Java]] and other JVM-compatible [[source code]] is [[compiler|compiled]].<ref name="oracle jvm spec">{{Cite web|url=http://docs.oracle.com/javase/specs/jvms/se8/html/|title=Java Virtual Machine Specification|publisher=Oracle|access-date=14 November 2023}}</ref> Each instruction is represented by a single [[byte]], hence the name [[bytecode]], making it a compact form of [[data]].<ref name="JVM Book">{{Cite book|last=Lindholm|first=Tim|title=The Java Virtual Machine Specification|year=2015|publisher=Oracle|isbn=978-0133905908}}</ref>
== Relation to Java ==
 
Due to the nature of bytecode, a Java bytecode [[computer program|program]] is runnable on any machine with a compatible JVM, without the lengthy process of compiling from source code.
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 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>.
 
Java bytecode is used at [[Runtime (program lifecycle phase)|runtime]] either [[interpreter (computing)|interpreted]] by a JVM or compiled to machine code via [[Just-in-time compilation|just-in-time]] (JIT) compilation and run as a native application.
== Generating bytecode ==
 
As Java bytecode is designed for a cross-platform compatibility and security, a Java bytecode application tends to run consistently across various [[computer hardware|hardware]] and [[software]] configurations.<ref>{{Cite journal|last=Arnold|first=Ken|title=The Java Programming Language|journal=Sun Microsystems|year=1996|volume=1|issue=1|pages=30–40}}</ref>
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 available, other parties have supplied compilers that produce Java bytecode. Examples of other compilers include:
* [[Jikes]], compiles from the Java programming language to Java bytecode developed by [[IBM]], implemented in [[C++]]
* Espresso, compiles from the Java programming language to Java bytecode, only Java 1.0
* [[GCJ|Gnu Compiler for Java]], GCJ, compiles from the Java programming language to Java bytecode, is also able to compile to native machine code.
 
== Relation to Java ==
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:
In general, a Java [[programmer]] does not need to understand Java bytecode or even be aware of it. 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|assembly]] helps the [[C (programming language)|C]] or [[C++]] programmer."<ref>{{Cite web |title=IBM Developer |url=https://developer.ibm.com/languages/java/ |access-date=20 February 2006 |website=developer.ibm.com}}</ref>
* [[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</ref>
* [[Jamaica (Java assembler)|Jamaica]], a 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.com/articles/jamaica.html</ref>
 
== Instruction set architecture ==
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
* [[Groovy programming language]], A scripting language based on Java
* [[C to Java byte-code compiler]]s
 
The bytecode comprises various instruction types, including data manipulation, control transfer, object creation and manipulation, and method invocation, all integral to Java's object-oriented programming model.<ref name="oracle jvm spec"/>
== Bytecode execution ==
 
The JVM is both a [[stack machine]] and a [[register machine]]. Each [[Call stack#STACK-FRAME|frame]] for a method call has an "operand stack" and an array of "local variables".<ref name="jvm">{{cite book |last1=Lindholm |first1=Tim |last2=Yellin |first2=Frank |last3=Bracha |first3=Gilad |last4=Buckley |first4=Alex |title=The Java Virtual Machine Specification |edition=Java SE 8 |date=2015-02-13 |url=http://docs.oracle.com/javase/specs/jvms/se8/html/}}</ref>{{rp|2.6}} <ref name="JVM Book"/> The operand stack is used for passing operands to computations and for receiving the return value of a called method, while local variables serve the same purpose as [[Processor register|registers]] and are also used to pass method arguments. The maximum size of the operand stack and local variable array, computed by the compiler, is part of the attributes of each method.<ref name="jvm"/>{{rp|4.7.3}} Each can be independently sized from 0 to 65535 values, where each value is 32 bits. {{code|lang="java"|long}} and {{code|lang="java"|double}} types, which are 64 bits, take up two consecutive local variables<ref name="jvm"/>{{rp|2.6.1}} (which need not be 64-bit aligned in the local variables array) or one value in the operand stack (but are counted as two units in the depth of the stack).<ref name="jvm"/>{{rp|2.6.2}}
Java bytecode is designed to be executed in [[Java virtual machine]]. There are several virtual machines available today both free or commercial.
 
=== Instruction set ===
{{See|Java virtual machine}}
 
{{further|List of Java bytecode instructions}}
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]].
 
Each [[bytecode]] is composed of one byte that represents the [[opcode]], along with zero or more bytes for operands.<ref name="jvm"/>{{rp|2.11}}
== Example ==
 
Of the 256 possible byte-long [[opcode]]s, {{as of|2015|lc=y}}, 202 are in use (~79%), 51 are reserved for future use (~20%), and 3 instructions (~1%) are permanently reserved for JVM implementations to use.<ref name="jvm"/>{{rp|6.2}} Two of these (<code>impdep1</code> and <code>impdep2</code>) are to provide traps for implementation-specific software and hardware, respectively. The third is used for debuggers to implement breakpoints.
Consider the following Java code.
 
Instructions fall into a number of broad groups:
<source lang="java">
* Load and store (e.g. <code>aload_0</code>, <code>istore</code>)
outer:
* Arithmetic and logic (e.g. <code>ladd</code>, <code>fcmpl</code>)
for (int i = 2; i < 1000; i++) {
* Type conversion (e.g. <code>i2b</code>, <code>d2i</code>)
for (int j = 2; j < i; j++) {
* Object creation and manipulation (<code>new</code>, <code>putfield</code>)
if (i % j == 0)
* Operand stack management (e.g. <code>swap</code>, <code>dup2</code>)
continue outer;
* Control transfer (e.g. <code>ifeq</code>, <code>goto</code>)
}
* Method invocation and return (e.g. <code>invokespecial</code>, <code>areturn</code>)
System.out.println (i);
}
</source>
 
There are also a few instructions for a number of more specialized tasks such as exception throwing, synchronization, etc.
A Java compiler might translate the Java code above into byte code as follows, assuming the above was put in a method:
 
Many instructions have [[Opcode prefix|prefixes]] and/or suffixes referring to the types of operands they operate on.<ref name="jvm"/>{{rp|2.11.1}} These are as follows:
<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==
{{howto}}
 
<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
|-
! Prefix/suffix !! Operand type
! colspan="5" | A
|-
| <code>i</code> || integer
| aaload || align="center" | 32 || || arrayref, index → value || loads onto the stack a reference from an array
|-
| <code>l</code> || long
| aastore || align="center" | 53 || || arrayref, index, value → || stores into a reference to an array
|-
| <code>s</code> || short
| aconst_null || align="center" | 01 || || → null || pushes a ''null'' reference onto the stack
|-
| <code>b</code> || byte
| aload || align="center" | 19 || index || → objectref || loads a reference onto the stack from a local variable ''#index''
|-
| <code>c</code> || character
| aload_0 || align="center" | 2a || || → objectref || loads a reference onto the stack from local variable 0
|-
| <code>f</code> || float
| aload_1 || align="center" | 2b || || → objectref || loads a reference onto the stack from local variable 1
|-
| <code>d</code> || double
| aload_2 || align="center" | 2c || || → objectref || loads a reference onto the stack from local variable 2
|-
| <code>a</code> || reference
| 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
|-
| 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'')
|-
| invokespecial || align="center" | b7 || indexbyte1, indexbyte2 || objectref, [arg1, arg2, ...] → || invoke instance method on object ''objectref'', 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"
|}
 
For example, <code>iadd</code> will add two integers, while <code>dadd</code> will add two doubles. The <code>const</code>, <code>load</code>, and <code>store</code> instructions may also take a suffix of the form <code>_''n''</code>, where ''n'' is a number from 0–3 for <code>load</code> and <code>store</code>. The maximum ''n'' for <code>const</code> differs by type.
==Notes==
<references />
 
The <code>const</code> instructions push a value of the specified type onto the stack. For example, <code>iconst_5</code> will push an integer (32 bit value) with the value 5 onto the stack, while <code>dconst_1</code> will push a double (64 bit floating point value) with the value 1 onto the stack. There is also an <code>aconst_null</code>, which pushes a {{code|lang=java|null}} reference. The ''n'' for the <code>load</code> and <code>store</code> instructions specifies the index in the local variable array to load from or store to. The <code>aload_0</code> instruction pushes the object in local variable 0 onto the stack (this is usually the <code>[[this (computer programming)|this]]</code> object). <code>istore_1</code> stores the integer on the top of the stack into local variable 1. For local variables beyond 3 the suffix is dropped and operands must be used.
==See also==
* [[Class (file format)|the Java .class file format]]
* [[C to Java Virtual Machine compilers]]
* [[ARM9E]], a [[Central processing unit|CPU]] family with direct Java bytecode execution ability
* [[Common Intermediate Language]] (CIL), a similar bytecode specification that runs on the [[Common Language Runtime|CLR]] of the [[.NET Framework]].
 
==External linksExample ==
*[http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html Sun's Java Virtual Machine Specification]
*[http://www.robert-tolksdorf.de/vmlanguages.html Programming Languages for the Java Virtual Machine]
 
Consider the following Java code:
{{Java (Sun)}}
 
<syntaxhighlight 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);
}
</syntaxhighlight>
 
A Java compiler might translate the Java code above into bytecode as follows, assuming the above was put in a method:
<syntaxhighlight lang="jasmin">
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
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</syntaxhighlight>
 
== Generation ==
{{Further|List of JVM languages}}
 
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:
*Eclipse compiler for Java (ECJ)
*[[Jikes]], compiles from Java to Java bytecode (developed by [[IBM]], implemented in [[C++]])
*Espresso, compiles from Java to Java bytecode (Java 1.0 only)
*[[GNU Compiler for Java]] (GCJ), compiles from Java to Java bytecode; it can also compile to native [[machine code]] and was part of the [[GNU Compiler Collection]] (GCC) up until version 6.
 
Some projects provide Java assemblers to enable writing Java bytecode by hand. Assembly code may be also generated by machine, for example by a compiler targeting a [[Java virtual machine]]. Notable Java assemblers include:
*[[Jasmin (Java assembler)|Jasmin]], takes text descriptions for Java classes, written in a simple assembly-like syntax using Java virtual machine instruction set and generates a Java class file<ref>{{Cite web|url=https://jasmin.sourceforge.net/|title=Jasmin Home Page|website=jasmin.sourceforge.net|accessdate=2 June 2024}}</ref>
*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>{{Cite web|url=https://www.javaworld.com/article/2072355/core-java/learn-to-speak-jamaican.html|title=Jamaica: The Java virtual machine (JVM) macro assembler<!-- Bot generated title -->|archive-url=https://web.archive.org/web/20231114000632/https://www.infoworld.com/article/2072355/learn-to-speak-jamaican.html|archive-date=14 November 2023|work=JavaWorld |accessdate=2 June 2024 |last1=Huang |first1=James Jianbo }}</ref>
*Krakatau Bytecode Tools, currently contains three tools: a decompiler and disassembler for Java classfiles and an assembler to create classfiles.<ref>{{Cite web|url=https://github.com/Storyyeller/Krakatau|title=Storyyeller/Krakatau|date=1 June 2024|accessdate=2 June 2024|via=GitHub}}</ref>
*Lilac, an assembler and disassembler for the [[Java virtual machine]].<ref>{{Cite web|url=https://lilac.sourceforge.net/|title=Lilac - a Java assembler|website=lilac.sourceforge.net|accessdate=2 June 2024}}</ref>
 
Others have developed compilers, for different programming languages, to target the Java virtual machine, such as:
*[[ColdFusion Markup Language|ColdFusion]]
*[[JRuby]] and [[Jython]], two [[scripting language]]s based on [[Ruby (programming language)|Ruby]] and [[Python (programming language)|Python]]
*[[Groovy (programming language)|Apache Groovy]], optionally typed and dynamic general-purpose language, with static-typing and static compilation capabilities
*[[Scala (programming language)|Scala]], a type-safe general-purpose programming language supporting object-oriented and functional programming
*[[JGNAT]] and AppletMagic, compile from the language [[Ada (programming language)|Ada]] to Java bytecode
*[[Java virtual machine#C to bytecode compilers|C to Java byte-code compiler]]s {{dead link|date=December 2018}}
*[[Clojure]], a functional, immutable, general-purpose programming language in the [[Lisp (programming language)|Lisp]] family with a strong emphasis on concurrency
*[[Kawa (Scheme implementation)|Kawa]], an implementation of the [[Scheme (programming language)|Scheme]] programming language, also a dialect of [[Lisp (programming language)|Lisp]].
*MIDletPascal
*[[JavaFX Script]] code is compiled to Java bytecode
*[[Kotlin (programming language)|Kotlin]], a statically-typed general-purpose programming language with type inference
*[[Object Pascal]] source code is compiled to Java bytecode using the [[Free Pascal]] 3.0+ compiler.<ref>{{Cite web|url=https://wiki.freepascal.org/FPC_New_Features_3.0|title=FPC New Features 3.0.0 - Free Pascal wiki|website=wiki.freepascal.org|accessdate=2 June 2024}}</ref><ref>{{Cite web|url=https://wiki.freepascal.org/FPC_JVM|title=FPC JVM - Free Pascal wiki|website=wiki.freepascal.org|accessdate=2 June 2024}}</ref>
 
== Execution ==
{{Further|Java virtual machine}}
 
There are several Java virtual machines available today to execute Java bytecode, both free and commercial products. If executing bytecode in a virtual machine is undesirable, a developer can also compile Java source code or bytecode directly to native machine code with tools such as the [[GNU Compiler for Java]] (GCJ). Some processors can execute Java bytecode natively. Such processors are termed ''[[Java processor]]s''.
 
== Support for dynamic languages ==
{{Further|List of JVM languages}}
 
The [[Java virtual machine]] provides some support for [[Type system#Dynamic typing|dynamically typed languages]]. Most of the extant JVM instruction set is [[Type system#Static typing|statically typed]] - in the sense that method calls have their signatures type-checked at [[compile time]], without a mechanism to defer this decision to [[Run time (program lifecycle phase)|run time]], or to choose the method dispatch by an alternative approach.<ref>{{cite web
| url=https://headius.blogspot.com/2007/01/invokedynamic-actually-useful.html
| title=InvokeDynamic: Actually Useful?
| date=2007-01-03
|last=Nutter|first=Charles
| access-date=2008-01-25}}</ref>
 
[[Java Community Process|JSR]] 292 (''Supporting Dynamically Typed Languages on the Java Platform'')<ref>{{Cite web|url=https://www.jcp.org/en/jsr/detail?id=292|title=The Java Community Process(SM) Program - JSRs: Java Specification Requests - detail JSR# 292|website=www.jcp.org|accessdate=2 June 2024}}</ref> added 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 extant 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. All JVMs supporting [[Java Platform, Standard Edition|JSE]] 7 also include the <code>invokedynamic</code> opcode.
 
== See also ==
{{Portal|Computer programming}}
<!---♦♦♦ Please keep the list in alphabetical order ♦♦♦--->
* Byte Code Engineering Library
* [[Common Intermediate Language]] (CIL), Microsoft's rival to Java bytecode
* [[Java backporting tools]]
* [[Java class file]]
* [[Java virtual machine]]
* [[JStik]]
* [[ObjectWeb ASM]]
* [[List of Java bytecode instructions]]
* [[List of JVM languages]]
 
== References ==
{{Reflist|2}}
 
== External links ==
{{listdev}}
{{Wikibooks|Java Programming|Byte Code|Java bytecode}}
* [http://docs.oracle.com/javase/specs/jvms/se8/html/ Oracle's Java Virtual Machine Specification]
* [http://www.is-research.de/info/vmlanguages/ Programming Languages for the Java Virtual Machine]
* [https://web.archive.org/web/20130618025348/http://www.drgarbage.com/bytecode-visualizer.html Bytecode Visualizer – bytecode viewer and debugger (free Eclipse plugin)]
* [https://web.archive.org/web/20090809232522/http://www.adaptj.com/main/stacktrace AdaptJ StackTrace – bytecode level debugging with a full control of the stack, the local variables, and the execution flow]
* [http://lulachronicles.blogspot.com Java Class Unpacker – plugin for Total Commander, it lets open class files as compressed archives and see fields and methods as files. The bytecode can be viewed as text using F3]
 
{{Java (Sun)}}
[[Category:Java platform|Bytecodes]]
[[Category:Assembly languages]]
 
[[Category:Assembly languages]]
[[bs:Java bytecode]]
[[esCategory:Java bytecodeplatform|Bytecodes]]
[[Category:Bytecodes]]
[[fr:Bytecode Java]]
[[pt:Bytecode Java]]
[[zh:Java bytecode]]