This document describes changes to the Java Virtual Machine Specification, as modified by the Better-defined JVM Class File Validation JEP, to clean up the specification's treatment of types. These changes facilitate introducing new typing features to support primitive objects.
All changes are presentational, with no intention to change the behavior of JVM implementations.
Most changes fall into one of the following areas:
Clarifying the treatment of
boolean
,byte
,short
, andchar
: they are legitimate types, but when placed on the stack, values of these types are implicitly converted toint
.Eliminating unnecessary references to
java.lang.Class
; instead, the representation of classes and interfaces is usually an implementation detail.Eliminating the notion of an "array class" which has a name and can be "loaded". Loading need only be concerned with converting
class
files to live classes and interfaces.Centralizing rules for identifying classes in descriptors that are subject to loader constraints.
Centralizing rules for testing that a value is an instance of a type.
Consistently specifying the interpretation of an array type that appears as the "referenced class" of a field or method reference. The
Object.clone
method requires special treatment.Removing unnecessary references to the Java language.
Changes are described with respect to existing sections of the JVM Specification. New text is indicated like this and deleted text is indicated like this. Explanation and discussion, as needed, is set aside in grey boxes.
To do: accessibility of array type receivers.
Chapter 2: The Structure of the Java Virtual Machine
2.2 Data Types
Like the Java programming language, the The Java Virtual Machine operates on two kinds of types: primitive types and reference types. There are, correspondingly, two kinds of values that can be stored in variables, passed as arguments, returned by methods, and operated upon: primitive values and reference values.
The Java Virtual Machine expects that nearly all type checking is done prior to run time, typically by a compiler, and does not have to be done by the Java Virtual Machine itself. Values of primitive types need not be tagged or otherwise be inspectable to determine their types at run time, or to be distinguished from values of reference types. Instead, the instruction set of the Java Virtual Machine distinguishes its operand types using instructions intended to operate on values of specific types. For instance, iadd, ladd, fadd, and dadd are all Java Virtual Machine instructions that add two numeric values and produce numeric results, but each is specialized for its operand type: int
, long
, float
, and double
, respectively. For a summary of type support in the Java Virtual Machine instruction set, see 2.11.1.
The Java Virtual Machine contains explicit support for objects. An object is either a dynamically allocated class instance or an array. A reference to an object is considered to have Java Virtual Machine type reference
. References are polymorphic: a single reference
may also be a value of multiple class types, interface types, or array types. Values of type reference
can be thought of as pointers to objects. More than one reference to an object may exist. Objects are always operated on, passed, and tested via values of type reference
.
2.6 Frames
2.6.1 Local Variables
Each frame (2.6) contains an array of variables known as its local variables. The length of the local variable array of a frame is determined at compile-time and supplied in the binary representation of a class or interface along with the code for the method associated with the frame (4.7.3).
A single local variable can hold a value of type boolean
, byte
, char
, short
,int
, float
, reference
, or returnAddress
. A pair of local variables can hold a value of type long
or double
.
Local variables are addressed by indexing. The index of the first local variable is zero. An integer is considered to be an index into the local variable array if and only if that integer is between zero and one less than the size of the local variable array.
A value of type long
or type double
occupies two consecutive local variables. Such a value may only be addressed using the lesser index. For example, a value of type double
stored in the local variable array at index n actually occupies the local variables with indices n and n+1; however, the local variable at index n+1 cannot be loaded from. It can be stored into. However, doing so invalidates the contents of local variable n.
The Java Virtual Machine does not require n to be even. In intuitive terms, values of types long
and double
need not be 64-bit aligned in the local variables array. Implementors are free to decide the appropriate way to represent such values using the two local variables reserved for the value.
The Java Virtual Machine uses local variables to pass parameters on method invocation. On class method invocation, any parameters are passed in consecutive local variables starting from local variable 0. On instance method invocation, local variable 0 is always used to pass a reference to the object on which the instance method is being invoked (this
in the Java programming language). Any parameters are subsequently passed in consecutive local variables starting from local variable 1.
2.11 Instruction Set Summary
2.11.1 Types and the Java Virtual Machine
Most of the instructions in the Java Virtual Machine instruction set encode type information about the operations they perform. For instance, the iload instruction (6.5.iload) loads the contents of a local variable, which must be an int
, onto the operand stack. The fload instruction (6.5.fload) does the same with a float
value. The two instructions may have identical implementations, but have distinct opcodes.
For the majority of typed instructions, the instruction type is represented explicitly in the opcode mnemonic by a letter: i for an int
operation, l for long
, s for short
, b for byte
, c for char
, f for float
, d for double
, and a for reference
. Some instructions for which the type is unambiguous do not have a type letter in their mnemonic. For instance, arraylength always operates on an object that is an array. Some instructions, such as goto, an unconditional control transfer, do not operate on typed operands.
Given the Java Virtual Machine's one-byte opcode size, encoding types into opcodes places pressure on the design of its instruction set. If each typed instruction supported all of the Java Virtual Machine's run-time data types, there would be more instructions than could be represented in a byte. Instead, the instruction set of the Java Virtual Machine provides a reduced level of type support for certain operations. In other words, the instruction set is intentionally not orthogonal. Separate instructions can be used to convert between unsupported and supported data types as necessary.
Table 2.11.1-A summarizes the type support in the instruction set of the Java Virtual Machine. A specific instruction, with type information, is built by replacing the T in the instruction template in the opcode column by the letter in the type column. If the type column for some instruction template and type is blank, then no instruction exists supporting that type of operation. For instance, there is a load instruction for type int
, iload, but there is no load instruction for type byte
.
Note that most instructions in Table 2.11.1-A do not have forms for the integral types byte
, char
, and short
. None have forms for the boolean
type. A compiler encodes loads of literal values of types Whenever values of types byte
and short
using Java Virtual Machine instructions that sign-extend those values to values of type int
at compile-time or run-time. Loads of literal values of types boolean
and char
are encoded using instructions that zero-extend the literal to a value of type int
at compile-time or run-time. Likewise, loads from arrays of values of type boolean
, byte
, short
, and char
are encoded using Java Virtual Machine instructions that sign-extend or zero-extend the values to values of type int
.byte
and short
are loaded onto the operand stack, they are implicitly converted by sign extension to values of type int
. Similarly, whenever values of types boolean
and char
are loaded onto the operand stack, they are implicitly converted by zero extension to values of type int
. Thus, most operations on values originally of actual types boolean
, byte
, char
, and short
are correctly performed by instructions operating on values of computational type int
.
Table 2.11.1-A. Type support in the Java Virtual Machine instruction set
opcode | byte |
short |
int |
long |
float |
double |
char |
reference |
---|---|---|---|---|---|---|---|---|
Tipush | bipush | sipush | ||||||
Tconst | iconst | lconst | fconst | dconst | aconst | |||
Tload | iload | lload | fload | dload | aload | |||
Tstore | istore | lstore | fstore | dstore | astore | |||
Tinc | iinc | |||||||
Taload | baload | saload | iaload | laload | faload | daload | caload | aaload |
Tastore | bastore | sastore | iastore | lastore | fastore | dastore | castore | aastore |
Tadd | iadd | ladd | fadd | dadd | ||||
Tsub | isub | lsub | fsub | dsub | ||||
Tmul | imul | lmul | fmul | dmul | ||||
Tdiv | idiv | ldiv | fdiv | ddiv | ||||
Trem | irem | lrem | frem | drem | ||||
Tneg | ineg | lneg | fneg | dneg | ||||
Tshl | ishl | lshl | ||||||
Tshr | ishr | lshr | ||||||
Tushr | iushr | lushr | ||||||
Tand | iand | land | ||||||
Tor | ior | lor | ||||||
Txor | ixor | lxor | ||||||
i2T | i2b | i2s | i2l | i2f | i2d | |||
l2T | l2i | l2f | l2d | |||||
f2T | f2i | f2l | f2d | |||||
d2T | d2i | d2l | d2f | |||||
Tcmp | lcmp | |||||||
Tcmpl | fcmpl | dcmpl | ||||||
Tcmpg | fcmpg | dcmpg | ||||||
if_TcmpOP | if_icmpOP | if_acmpOP | ||||||
Treturn | ireturn | lreturn | freturn | dreturn | areturn |
The mapping between Java Virtual Machine actual original types and Java Virtual Machine computational types is summarized by Table 2.11.1-B.
Certain Java Virtual Machine instructions such as pop and swap operate on the operand stack without regard to type; however, such instructions are constrained to use only on values of certain categories of computational types, also given in Table 2.11.1-B.
Table 2.11.1-B. Actual Original and Computational types in the Java Virtual Machine
Computational type | Category | |
---|---|---|
boolean |
int |
1 |
byte |
int |
1 |
char |
int |
1 |
short |
int |
1 |
int |
int |
1 |
float |
float |
1 |
reference |
reference |
1 |
returnAddress |
returnAddress |
1 |
long |
long |
2 |
double |
double |
2 |
2.11.2 Load and Store Instructions
The load and store instructions transfer values between the local variables (2.6.1) and the operand stack (2.6.2) of a Java Virtual Machine frame (2.6):
Load a local variable onto the operand stack: iload, iload_<n>, lload, lload_<n>, fload, fload_<n>, dload, dload_<n>, aload, aload_<n>.
Store a value from the operand stack into a local variable: istore, istore_<n>, lstore, lstore_<n>, fstore, fstore_<n>, dstore, dstore_<n>, astore, astore_<n>.
Load a constant on to the operand stack: bipush, sipush, ldc, ldc_w, ldc2_w, aconst_null, iconst_m1, iconst_<i>, lconst_<l>, fconst_<f>, dconst_<d>.
Gain access to more local variables using a wider index, or to a larger immediate operand: wide.
Instructions that access fields of objects and elements of arrays (2.11.5) also transfer data to and from the operand stack.
Instruction mnemonics shown above with trailing letters between angle brackets (for instance, iload_<n>) denote families of instructions (with members iload_0, iload_1, iload_2, and iload_3 in the case of iload_<n>). Such families of instructions are specializations of an additional generic instruction (iload) that takes one operand. For the specialized instructions, the operand is implicit and does not need to be stored or fetched. The semantics are otherwise the same (iload_0 means the same thing as iload with the operand 0). The letter between the angle brackets specifies the type of the implicit operand for that family of instructions: for <n>, a nonnegative integer; for <i>, an int
; for <l>, a long
; for <f>, a float
; and for <d>, a double
. Forms for type int
are used in many cases to perform operations on values of type byte
, char
, and short
(2.11.1).
This notation for instruction families is used throughout this specification.
2.11.8 Method Invocation and Return Instructions
The following five instructions invoke methods:
invokevirtual invokes an instance method of an object, dispatching on the (virtual) type of the object.
This is the normal method dispatch in the Java programming language.invokeinterface invokes an interface method, searching the methods implemented by the particular run-time object to find the appropriate method.
invokespecial invokes an instance method requiring special handling, either an instance initialization method (2.9.1) or a method of the current class or its supertypes.
invokestatic invokes a class (
static
) method in a named class.invokedynamic invokes the method which is the target of the call site object bound to the invokedynamic instruction. The call site object was bound to a specific lexical occurrence of the invokedynamic instruction by the Java Virtual Machine as a result of running a bootstrap method before the first execution of the instruction. Therefore, each occurrence of an invokedynamic instruction has a unique linkage state, unlike the other instructions which invoke methods.
The method return instructions, which are distinguished by return type, are ireturn (used to return values of type , lreturn, freturn, dreturn, and areturn. In addition, the return instruction is used to return from methods declared to be void.boolean
, byte
, char
, short
, or int
)
Chapter 4: The class
File Format
4.3 Descriptors
A descriptor is a string representing the type of a field or method. Descriptors are represented in the class
file format using modified UTF-8 strings (4.4.7) and thus may be drawn, where not further constrained, from the entire Unicode codespace.
4.3.1 Grammar Notation
Descriptors are specified using a grammar. The grammar is a set of productions that describe how sequences of characters can form syntactically correct descriptors of various kinds. Terminal symbols of the grammar are shown in fixed width
font, and should be interpreted as ASCII characters. Nonterminal symbols are shown in italic type. The definition of a nonterminal is introduced by the name of the nonterminal being defined, followed by a colon. One or more alternative definitions for the nonterminal then follow on succeeding lines.
The syntax {x} on the right-hand side of a production denotes zero or more occurrences of x.
The phrase (one of) on the right-hand side of a production signifies that each of the terminal symbols on the following line or lines is an alternative definition.
4.3.2 Field Descriptors
A field descriptor represents the type of a class, instance field, parameter, value, or local variable.
- FieldDescriptor:
- FieldType
- FieldType:
- BaseType
ObjectTypeClassType- ArrayType
- BaseType:
- (one of)
B
C
D
F
I
J
S
Z
ObjectType:ClassType:L
ClassName;
- ArrayType:
[
ComponentType- ComponentType:
- FieldType
The characters of BaseType, the L
and ;
of ObjectType, and the [
of ArrayType are all ASCII characters.
ClassName represents a binary class or interface name encoded in internal form (4.2.1).
A field descriptor mentions a class or interface name if the name appears as a ClassName in the descriptor. This includes a ClassName nested in the ComponentType of an ArrayType.
This definition of mentions allows us to eliminate boilerplate in a handful of other sections and gives us a single location to identify the classes that are subject to loading constraints, resolution, etc. The definition is flexible enough to support new kinds of types that may be added in the future.
The interpretation of field descriptors as types is shown in Table 4.3-A. See 2.2, 2.3, and 2.4 for the meaning of these types.
A field descriptor representing an array type is valid only if it represents a type with 255 or fewer dimensions.
Table 4.3-A. Interpretation of field descriptors
FieldType term | Type | |
---|---|---|
B |
byte |
|
C |
char |
|
D |
double |
|
F |
float |
|
I |
int |
|
J |
long |
|
L ClassName ; |
reference |
|
S |
short |
|
Z |
boolean |
true or false |
[ |
reference |
The field descriptor of an instance variable of type
int
is simplyI
.The field descriptor of an instance variable of type
Object
isLjava/lang/Object;
. Note that the internal form of the binary name for classObject
is used.The field descriptor of an instance variable of the multidimensional array type
double[][][]
is[[[D
.
The "Interpretation" column of Table 4.3-A is redundant; these details are better left to sections 2.2, 2.3 and 2.4.
4.3.3 Method Descriptors
A method descriptor contains zero or more parameter descriptors, representing the types of parameters that the method takes, and a return descriptor, representing the type of the value (if any) that the method returns.
- MethodDescriptor:
(
{ParameterDescriptor})
ReturnDescriptor- ParameterDescriptor:
- FieldType
- ReturnDescriptor:
- FieldType
- VoidDescriptor
- VoidDescriptor:
V
The character V
indicates that the method returns no value (its result is void
).
A method descriptor mentions a class or interface name if the name appears as a ClassName in the FieldType of a parameter descriptor or return descriptor.
The method descriptor for the method:
Object m(int i, double d, Thread t) {...}
is:
(IDLjava/lang/Thread;)Ljava/lang/Object;
Note that the internal forms of the binary names of
Thread
andObject
are used.
A method descriptor is valid only if it represents method parameters with a total length of 255 or less, where that length includes the contribution for this
in the case of instance or interface method invocations. The total length is calculated by summing the contributions of the individual parameters, where a parameter of type long
or double
contributes two units to the length and a parameter of any other type contributes one unit.
A method descriptor is the same whether the method it describes is a class method or an instance method. Although an instance method is passed this
, a reference to the object on which the method is being invoked, in addition to its intended arguments, that fact is not reflected in the method descriptor. The reference to this
is passed implicitly by the Java Virtual Machine instructions which invoke instance methods (2.6.1, 4.11).
4.7 Attributes
4.7.16 The RuntimeVisibleAnnotations
Attribute
4.7.16.1 The element_value
structure
- class_info_index
The
class_info_index
item denotes a class literal as the value of this element-value pair.The
class_info_index
item should be a valid index into theconstant_pool
table. Theconstant_pool
entry at that index should be aCONSTANT_Utf8_info
structure (4.4.7) representing a return descriptor (4.3.3). The return descriptor gives the type corresponding to the class literal represented by thiselement_value
structure. Types correspond to class literals as follows:For a class literal C
.class
, where C is the name of a class,or interface, or array type, the corresponding type is C. The return descriptor in theconstant_pool
should bean ObjectType or an ArrayTypea ClassType.For a class literal T[]
.class
, where T[] is an array type, the corresponding type is T[]. The return descriptor in theconstant_pool
should be an ArrayType.For a class literal p
.class
, where p is the name of a primitive type, the corresponding type is p. The return descriptor in theconstant_pool
should be a BaseType character.For a class literal
void.class
, the corresponding type isvoid
. The return descriptor in theconstant_pool
should be V.
For example, the class literal
Object.class
corresponds to the typeObject
, so theconstant_pool
entry isLjava/lang/Object;
, whereas the class literalint.class
corresponds to the typeint
, so theconstant_pool
entry isI
.The class literal
void.class
corresponds tovoid
, so theconstant_pool
entry is V, whereas the class literalVoid.class
corresponds to the typeVoid
, so theconstant_pool
entry isLjava/lang/Void;
.
...
4.9 Constraints on Java Virtual Machine Code
4.9.2 Structural Constraints
The structural constraints on the code in a class
file specify constraints on relationships between Java Virtual Machine instructions, exception handlers, and stack maps. The structural constraints are as follows:
For each stack map table entry, the bytecode offset specified by the frame must be a valid index into the
Code
array, and must be the index of the opcode of an instruction.Each instruction must only be executed with the appropriate type and number of arguments in the operand stack and local variable array, regardless of the execution path that leads to its invocation.
An instruction operating on values of typeint
is also permitted to operate on values of typeboolean
,byte
,char
, andshort
.As noted in 2.3.4 and 2.11.1, the Java Virtual Machine
internallyimplicitly converts values of typesboolean
,byte
,short
, andchar
to typeint
, allowing instructions expecting values of typeint
to operate on them.
...
Chapter 5: Loading, Linking, and Initializing
5.1 The Run-Time Constant Pool
The Java Virtual Machine maintains a run-time constant pool for each class and interface (2.5.5). This data structure serves many of the purposes of the symbol table of a conventional programming language implementation. The constant_pool
table in the binary representation of a class or interface (4.4) is used to construct the run-time constant pool upon class or interface creation (5.3).
There are two kinds of entry in the run-time constant pool: symbolic references, which may later be resolved (5.4.3), and static constants, which require no further processing.
The symbolic references in the run-time constant pool are derived from entries in the constant_pool
table in accordance with the structure of each entry:
A symbolic reference to a class,
orinterface, or array type is derived from aCONSTANT_Class_info
structure (4.4.1).Such a reference gives the name of the class or interface in the following form:Such a reference gives the name of a class or interface, or the field descriptor representation of an array type, as described in 4.4.1.For a nonarray class or an interface, the name is the binary name (4.2.1) of the class or interface.For an array class of n dimensions, the name begins with n occurrences of the ASCII[
character followed by a representation of the element type:If the element type is a primitive type, it is represented by the corresponding field descriptor (4.3.2).Otherwise, if the element type is a reference type, it is represented by the ASCIIL
character followed by the binary name of the element type followed by the ASCII;
character.
Whenever this chapter refers to the name of a class or interface, the name should be understood to be in the form above.(This is also the form returned by theClass.getName
method.)This extended description of the form of the
CONSTANT_Class_info
attribute is redundant and better left to section 4.4.1.A symbolic reference to a field of a class or an interface is derived from a
CONSTANT_Fieldref_info
structure (4.4.2). Such a reference gives the name and descriptor of the field, as well as a symbolic reference to the class,orinterface, or array type in which the field is to be found.A symbolic reference to a method of a class is derived from a
CONSTANT_Methodref_info
structure (4.4.2). Such a reference gives the name and descriptor of the method, as well as a symbolic reference to the class, interface, or array type in which the method is to be found.A symbolic reference to a method of an interface is derived from a
CONSTANT_InterfaceMethodref_info
structure (4.4.2). Such a reference gives the name and descriptor of the interface method, as well as a symbolic reference to the class, interface, or array type in which the method is to be found.A symbolic reference to a method handle is derived from a
CONSTANT_MethodHandle_info
structure (4.4.8). Such a reference gives a symbolic reference to a field of a class or interface, or a method of a class, or a method of an interface, depending on the kind of the method handle.A symbolic reference to a method type is derived from a
CONSTANT_MethodType_info
structure (4.4.9). Such a reference gives a method descriptor (4.3.3).A symbolic reference to a dynamically-computed constant is derived from a
CONSTANT_Dynamic_info
structure (4.4.10). Such a reference gives:a symbolic reference to a method handle, which will be invoked to compute the constant's value;
a sequence of symbolic references and static constants, which will serve as static arguments when the method handle is invoked;
an unqualified name and a field descriptor.
A symbolic reference to a dynamically-computed call site is derived from a
CONSTANT_InvokeDynamic_info
structure (4.4.10). Such a reference gives:a symbolic reference to a method handle, which will be invoked in the course of an invokedynamic instruction (6.5.invokedynamic) to compute an instance of
java.lang.invoke.CallSite
;a sequence of symbolic references and static constants, which will serve as static arguments when the method handle is invoked;
an unqualified name and a method descriptor.
The static constants in the run-time constant pool are also derived from entries in the constant_pool
table in accordance with the structure of each entry:
A string constant is a
reference
to an instance of classString
, and is derived from aCONSTANT_String_info
structure (4.4.3). To derive a string constant, the Java Virtual Machine examines the sequence of code points given by theCONSTANT_String_info
structure:If the method
String.intern
has previously been invoked on an instance of classString
containing a sequence of Unicode code points identical to that given by theCONSTANT_String_info
structure, then the string constant is areference
to that same instance of classString
.Otherwise, a new instance of class
String
is created containing the sequence of Unicode code points given by theCONSTANT_String_info
structure. The string constant is areference
to the new instance. Finally, the methodString.intern
is invoked on the new instance.
Numeric constants are derived from
CONSTANT_Integer_info
,CONSTANT_Float_info
,CONSTANT_Long_info
, andCONSTANT_Double_info
structures (4.4.4, 4.4.5).Note that
CONSTANT_Float_info
structures represent values in IEEE 754 single format andCONSTANT_Double_info
structures represent values in IEEE 754 double format. The numeric constants derived from these structures must thus be values that can be represented using IEEE 754 single and double formats, respectively.
The remaining structures in the constant_pool
table - the descriptive structures CONSTANT_NameAndType_info
, CONSTANT_Module_info
, and CONSTANT_Package_info
, and the foundational structure CONSTANT_Utf8_info
- are only used indirectly when constructing the run-time constant pool. No entries in the run-time constant pool correspond directly to these structures.
Some entries in the run-time constant pool are loadable, which means:
They may be pushed onto the stack by the ldc family of instructions (6.5.ldc, 6.5.ldc_w, 6.5.ldc2_w).
They may be static arguments to bootstrap methods for dynamically-computed constants and call sites (5.4.3.6).
An entry in the run-time constant pool is loadable if it is derived from an entry in the constant_pool
table that is loadable (see Table 4.4-C). Accordingly, the following entries in the run-time constant pool are loadable:
Symbolic references to classes,
andinterfaces, and array typesSymbolic references to method handles
Symbolic references to method types
Symbolic references to dynamically-computed constants
Static constants
5.3 Creation and Loading
Creation of a class or interface C denoted by the name N consists of the construction in the method area of the Java Virtual Machine (2.5.4) of an implementation-specific internal representation of C. Class or interface creation is triggered by another class or interface D, which references C through its run-time constant pool. Class or interface creation may also be triggered by D invoking methods in certain Java SE Platform class libraries (2.12) such as reflection.
If C is not an array class, it is created by loading a binary representation of C (4) using a class loader. Array classes do not have an external binary representation; they are created by the Java Virtual Machine rather than by a class loader.
A class or interface is created by loading a binary representation of the class or interface (4) using a class loader. There are two kinds of class loaders: the bootstrap class loader supplied by the Java Virtual Machine, and user-defined class loaders. Every user-defined class loader is an instance of a subclass of the abstract class ClassLoader
. Applications employ user-defined class loaders in order to extend the manner in which the Java Virtual Machine dynamically loads and thereby creates classes. User-defined class loaders can be used to create classes that originate from user-defined sources. For example, a class could be downloaded across a network, generated on the fly, or extracted from an encrypted file.
A class loader L may create C by defining it directly or by delegating to another class loader. If L creates C directly, we say that L defines C or, equivalently, that L is the defining loader of C.
When one class loader delegates to another class loader, the loader that initiates the loading is not necessarily the same loader that completes the loading and defines the class. If L creates C, either by defining it directly or by delegation, we say that L initiates loading of C or, equivalently, that L is an initiating loader of C.
At run time, a class or interface is determined not by its name alone, but by a pair: its binary name (4.2.1) and its defining class loader. Each such class or interface belongs to a single run-time package. The run-time package of a class or interface is determined by the package name and defining class loader of the class or interface.
The Java Virtual Machine uses one of three two procedures to create class or interface C denoted by N:
If N denotes a nonarray class or an interface, one of the two following methods is used to load and thereby create C:If D was defined by the bootstrap class loader, then the bootstrap class loader initiates loading of C (5.3.1).
If D was defined by a user-defined class loader, then that same user-defined class loader initiates loading of C (5.3.2).
Otherwise N denotes an array class. An array class is created directly by the Java Virtual Machine (5.3.3), not by a class loader. However, the defining class loader of D is used in the process of creating array class C.
If an error occurs during class loading, then an instance of a subclass of LinkageError
must be thrown at a point in the program that (directly or indirectly) uses the class or interface being loaded.
If the Java Virtual Machine ever attempts to load a class C during verification (5.4.1) or resolution (5.4.3) (but not initialization (5.5)), and the class loader that is used to initiate loading of C throws an instance of ClassNotFoundException
, then the Java Virtual Machine must throw an instance of NoClassDefFoundError
whose cause is the instance of ClassNotFoundException
.
(A subtlety here is that recursive class loading to load superclasses is performed as part of resolution (5.3.5, step 3). Therefore, a ClassNotFoundException
that results from a class loader failing to load a superclass must be wrapped in a NoClassDefFoundError
.)
A well-behaved class loader should maintain three properties:
Given the same name, a good class loader should always return the same
Class
object.If a class loader L1 delegates loading of a class C to another loader L2, then for any type T that occurs as the direct superclass or a direct superinterface of C, or as the type of a field in C, or as the type of a formal parameter of a method or constructor in C, or as a return type of a method in C, L1 and L2 should return the same
Class
object.If a user-defined classloader prefetches binary representations of classes and interfaces, or loads a group of related classes together, then it must reflect loading errors only at points in the program where they could have arisen without prefetching or group loading.
We will sometimes represent a class or interface using the notation <
N, Ld>
, where N denotes the name of the class or interface and Ld denotes the defining loader of the class or interface.
We will also represent a class or interface using the notation NLi, where N denotes the name of the class or interface and Li denotes an initiating loader of the class or interface.
5.3.1 Loading Using the Bootstrap Class Loader
The following steps are used to load and thereby create the nonarray class or interface C denoted by N using the bootstrap class loader.
First, the Java Virtual Machine determines whether the bootstrap class loader has already been recorded as an initiating loader of a class or interface denoted by N. If so, this class or interface is C, and no class creation is necessary.
Otherwise, the Java Virtual Machine passes the argument N to an invocation of a method on the bootstrap class loader to search for a purported representation of C in a platform-dependent manner. Typically, a class or interface will be represented using a file in a hierarchical file system, and the name of the class or interface will be encoded in the pathname of the file.
Note that there is no guarantee that a purported representation found is valid or is a representation of C. This phase of loading must detect the following error:
- If no purported representation of C is found, loading throws an instance of
ClassNotFoundException
.
Then the Java Virtual Machine attempts to derive a class denoted by N using the bootstrap class loader from the purported representation using the algorithm found in 5.3.5. That class is C.
5.3.2 Loading Using a User-defined Class Loader
The following steps are used to load and thereby create the nonarray class or interface C denoted by N using a user-defined class loader L.
First, the Java Virtual Machine determines whether L has already been recorded as an initiating loader of a class or interface denoted by N. If so, this class or interface is C, and no class creation is necessary.
Otherwise, the Java Virtual Machine invokes loadClass(N)
on L. The value returned by the invocation is the created class or interface C. The Java Virtual Machine then records that L is an initiating loader of C (5.3.4). The remainder of this section describes this process in more detail.
When the loadClass
method of the class loader L is invoked with the name N of a class or interface C to be loaded, L must perform one of the following two operations in order to load C:
The class loader L can create an array of bytes representing C as the bytes of a
ClassFile
structure (4.1); it then must invoke the methoddefineClass
of classClassLoader
. InvokingdefineClass
causes the Java Virtual Machine to derive a class or interface denoted by N using L from the array of bytes using the algorithm found in 5.3.5.The class loader L can delegate the loading of C to some other class loader L'. This is accomplished by passing the argument N directly or indirectly to an invocation of a method on L' (typically the
loadClass
method). The result of the invocation is C.
In either (1) or (2), if the class loader L is unable to load a class or interface denoted by N for any reason, it must throw an instance of ClassNotFoundException
.
Since JDK 1.1, Oracle’s Java Virtual Machine implementation has invoked the
loadClass
method of a class loader in order to cause it to load a class or interface. The argument toloadClass
is the name of the class or interface to be loaded. There is also a two-argument version of theloadClass
method, where the second argument is aboolean
that indicates whether the class or interface is to be linked or not. Only the two-argument version was supplied in JDK 1.0.2, and Oracle’s Java Virtual Machine implementation relied on it to link the loaded class or interface. From JDK 1.1 onward, Oracle’s Java Virtual Machine implementation links the class or interface directly, without relying on the class loader.
5.3.3 Creating Array Classes
The following steps are used to create the array class C denoted by N using class loader L. Class loader L may be either the bootstrap class loader or a user-defined class loader.
If L has already been recorded as an initiating loader of an array class with the same component type as N, that class is C, and no array class creation is necessary.
Otherwise, the following steps are performed to create C:
If the component type is a
reference
type, the algorithm of this section (5.3) is applied recursively using class loader L in order to load and thereby create the component type of C.The Java Virtual Machine creates a new array class with the indicated component type and number of dimensions.
If the component type is a
reference
type, C is marked as having been defined by the defining class loader of the component type. Otherwise, C is marked as having been defined by the bootstrap class loader.In any case, the Java Virtual Machine then records that L is an initiating loader for C (5.3.4).
If the component type is a
reference
type, the accessibility of the array class is determined by the accessibility of its component type (5.4.4). Otherwise, the array class is accessible to all classes and interfaces.
Deleting this section will necessitate a renumbering or restructuring of the subsequent sections.
Wherever loading constraints are generated (5.4.2, 5.4.3.2, 5.4.3.3), the specification already excludes array types, suggesting that there is no need to track initiating and defining loaders of array types.
Similarly, access checking occurs on the element type of an array type, and need not be repeated for the array type itself (5.4.3.1).
5.3.4 Loading Constraints
Ensuring type safe linkage in the presence of class loaders requires special care. It is possible that when two different class loaders initiate loading of a class or interface denoted by N, the name N may denote a different class or interface in each loader.
When a class or interface C = <
N1, L1>
makes a symbolic reference to a field or method of another class or interface D = <
N2, L2>
, the symbolic reference includes a descriptor specifying the type of the field, or the return and argument types of the method. It is essential that any type class or interface name N mentioned in the field or method descriptor (4.3.1, 4.3.2) denote the same class or interface when loaded by L1 and when loaded by L2.
To ensure this, the Java Virtual Machine imposes loading constraints of the form NL1 = NL2 during preparation (5.4.2) and resolution (5.4.3). To enforce these constraints, the Java Virtual Machine will, at certain prescribed times (see 5.3.1, 5.3.2, 5.3.3, and 5.3.5), record that a particular loader is an initiating loader of a particular class. After recording that a loader is an initiating loader of a class, the Java Virtual Machine must immediately check to see if any loading constraints are violated. If so, the record is retracted, the Java Virtual Machine throws a LinkageError
, and the loading operation that caused the recording to take place fails.
Similarly, after imposing a loading constraint (see 5.4.2, 5.4.3.2, 5.4.3.3, and 5.4.3.4), the Java Virtual Machine must immediately check to see if any loading constraints are violated. If so, the newly imposed loading constraint is retracted, the Java Virtual Machine throws a LinkageError
, and the operation that caused the constraint to be imposed (either resolution or preparation, as the case may be) fails.
The situations described here are the only times at which the Java Virtual Machine checks whether any loading constraints have been violated. A loading constraint is violated if, and only if, all the following four conditions hold:
There exists a loader L such that L has been recorded by the Java Virtual Machine as an initiating loader of a class C named N.
There exists a loader L' such that L' has been recorded by the Java Virtual Machine as an initiating loader of a class C ' named N.
The equivalence relation defined by the (transitive closure of the) set of imposed constraints implies NL = NL'.
C ≠ C '.
A full discussion of class loaders and type safety is beyond the scope of this specification. For a more comprehensive discussion, readers are referred to Dynamic Class Loading in the Java Virtual Machine by Sheng Liang and Gilad Bracha (Proceedings of the 1998 ACM SIGPLAN Conference on Object-Oriented Programming Systems, Languages and Applications).
5.3.5 Deriving a Class from a class
File Representation
The following steps are used to derive a Class
object for the nonarray class or interface C denoted by N using loader L from a purported representation in class
file format.
5.4 Linking
5.4.2 Preparation
Preparation involves creating the static fields for a class or interface and initializing such fields to their default values (2.3, 2.4). This does not require the execution of any Java Virtual Machine code; explicit initializers for static fields are executed as part of initialization (5.5), not preparation.
During preparation of a class or interface C, the Java Virtual Machine also imposes loading constraints (5.3.4):
Let L1 be the defining loader of C. For each instance method m declared in C that can override (5.4.5) an instance method declared in a superclass or superinterface
<
D, L2>
,the Java Virtual Machine imposes loading constraints as followsfor each class or interface name N mentioned by the descriptor of m (4.3.3), the Java Virtual Machine imposes the loading constraint NL1 = NL2.Given that the return type of m is Tr, and that the formal parameter types of m are Tf1, ..., Tfn:If Tr not an array type, let T0 be Tr; otherwise, let T0 be the element type of Tr.For i = 1 to n: If Tfi is not an array type, let Ti be Tfi; otherwise, let Ti be the element type of Tfi.Then TiL1 = TiL2 for i = 0 to n.For each instance method m declared in a superinterface
<
I, L3>
of C, if C does not itself declare an instance method that can override m, then a method is selected (5.4.6) with respect to C and the method m in<
I, L3>
. Let<
D, L2>
be the class or interface that declares the selected method.The Java Virtual Machine imposes loading constraints as follows.For each class or interface name N mentioned by the descriptor of m, the Java Virtual Machine imposes the loading constraint NL2 = NL3.Given that the return type of m is Tr, and that the formal parameter types of m are Tf1, ..., Tfn:If Tr not an array type, let T0 be Tr; otherwise, let T0 be the element type of Tr.For i = 1 to n: If Tfi is not an array type, let Ti be Tfi; otherwise, let Ti be the element type of Tfi.Then TiL2 = TiL3 for i = 0 to n.
Preparation may occur at any time following creation but must be completed prior to initialization.
5.4.3 Resolution
Many Java Virtual Machine instructions - anewarray, checkcast, getfield, getstatic, instanceof, invokedynamic, invokeinterface, invokespecial, invokestatic, invokevirtual, ldc, ldc_w, ldc2_w, multianewarray, new, putfield, and putstatic - rely on symbolic references in the run-time constant pool. Execution of any of these instructions requires resolution of the symbolic reference.
Resolution is the process of dynamically determining one or more concrete values from a symbolic reference in the run-time constant pool. Initially, all symbolic references in the run-time constant pool are unresolved.
Resolution of an unresolved symbolic reference to (i) a class, or interface, or array type, (ii) a field, (iii) a method, (iv) a method type, (v) a method handle, or (vi) a dynamically-computed constant, proceeds in accordance with the rules given in 5.4.3.1 through 5.4.3.5 5.4.3.6.
5.4.3.1 Class, and Interface, and Array Type Resolution
To resolve an unresolved symbolic reference from D to a class or interface C denoted by N, the following steps are performed:
The defining class loader of D is used to create a class or interface denoted by N. This class or interface is C. The details of the process are given in 5.3.
Any exception that can be thrown as a result of failure of class or interface creation can thus be thrown as a result of failure of class and interface resolution.
If C is an array class and its element type is areference
type, then a symbolic reference to the class or interface representing the element type is resolved by invoking the algorithm in 5.4.3.1 recursively.Finally, accessAccess control is applied for the access from D to C (5.4.4).
To resolve an unresolved symbolic reference from D to an array type T, the following steps are performed:
If the element type of the array type is a class or interface type, the named class or interface is resolved, as if by resolution of an unresolved symbolic reference to the named class or interface.
A representation of the array type denoted by the symbolic reference is created.
If steps 1 and 2 succeed but step 3 fails, C is still valid and usable. Nevertheless, resolution fails, and D is prohibited from accessing C. If resolution of a class, interface, or array type successfully loads a class or interface, but a subsequent step (such as access checking) fails, the class or interface is still valid and usable. Nevertheless, resolution fails, and the symbolic reference that was being resolved is invalid.
5.4.3.2 Field Resolution
To resolve an unresolved symbolic reference from D to a field in a class, or interface, or array type C, the symbolic reference to C given by the field reference must first be resolved (5.4.3.1). Therefore, any exception that can be thrown as a result of failure of resolution of a class or interface reference to a class, interface, or array type can be thrown as a result of failure of field resolution. If the reference to C can be successfully resolved, an exception relating to the failure of resolution of the field reference itself can be thrown.
When resolving a field reference, field resolution first attempts to look up the referenced field in C and its superclasses:
If C is a class or interface that declares a field with the name and descriptor specified by the field reference, field lookup succeeds. The declared field is the result of the field lookup.
Otherwise, field lookup is applied recursively to the direct superinterfaces of
the specified class or interfaceC. The direct superinterfaces of an array type areCloneable
andjava.io.Serializable
(as loaded by the bootstrap class loader).Otherwise, if C has a direct superclass S, field lookup is applied recursively to S. The direct superclass of an array type is
Object
.Otherwise, field lookup fails.
Then, the result of field resolution is determined:
If field lookup failed, field resolution throws a
NoSuchFieldError
.Otherwise, field lookup succeeded. Access control is applied for the access from D to the field which is the result of field lookup (5.4.4). Then:
If access control failed, field resolution fails for the same reason.
Otherwise, access control succeeded. Loading constraints are imposed, as follows.
Let
<
E, L1>
be the class or interface in which the referenced field is actually declared. Let L2 be the defining loader of D.Given that the type of the referenced field is Tf: if Tf is not an array type, let T be Tf; otherwise, let T be the element type of Tf.The Java Virtual Machine imposes the loading constraint that TL1 = TL2.For any class or interface name N mentioned by the descriptor of the referenced field (4.3.2), the Java Virtual Machine imposes the loading constraint NL1 = NL2 (5.3.4).
If imposing this constraint results in any loading constraints being violated (5.3.4), then field resolution fails. Otherwise, field resolution succeeds.
5.4.3.3 Method Resolution
To resolve an unresolved symbolic reference from D to a method in a class or array type C, the symbolic reference to C given by the method reference is first resolved (5.4.3.1). Therefore, any exception that can be thrown as a result of failure of resolution of a class reference to a class, interface, or array type can be thrown as a result of failure of method resolution. If the reference to C can be successfully resolved, exceptions relating to the resolution of the method reference itself can be thrown.
When resolving a method reference:
If C is an interface, method resolution throws an
IncompatibleClassChangeError
.Otherwise, method resolution attempts to locate the referenced method in C and its superclasses:
If C is a class that declares exactly one method with the name specified by the method reference, and the declaration is a signature polymorphic method (2.9.3), then method lookup succeeds.
All the class names mentioned in the descriptor are resolved (5.4.3.1).The descriptor specified by the method reference is resolved, as if by resolution of an unresolved symbolic reference to a method type (5.4.3.5).The resolved method is the signature polymorphic method declaration. It is not necessary for C to declare a method with the descriptor specified by the method reference.
Otherwise, if C is a class that declares a method with the name and descriptor specified by the method reference, method lookup succeeds.
Otherwise, if C is a class and has a superclass, step 2 of method resolution is recursively invoked on the direct superclass of C.
Otherwise, if C is an array type and the class
Object
declares a method with the name and descriptor specified by the method reference, method lookup succeeds.
Otherwise, method resolution attempts to locate the referenced method in the superinterfaces of
the specified classC:If the maximally-specific superinterface methods of C for the name and descriptor specified by the method reference include exactly one method that does not have its
ACC_ABSTRACT
flag set, then this method is chosen and method lookup succeeds.Otherwise, if any superinterface of C declares a method with the name and descriptor specified by the method reference that has neither its
ACC_PRIVATE
flag nor itsACC_STATIC
flag set, one of these is arbitrarily chosen and method lookup succeeds.Otherwise, method lookup fails.
A maximally-specific superinterface method of a class, or interface, or array type C for a particular method name and descriptor is any method for which all of the following are true:
The method is declared in a superinterface (direct or indirect) of C. The direct superinterfaces of an array type are
Cloneable
andjava.io.Serializable
(as loaded by the bootstrap class loader).The method is declared with the specified name and descriptor.
The method has neither its
ACC_PRIVATE
flag nor itsACC_STATIC
flag set.Where the method is declared in interface I, there exists no other maximally-specific superinterface method of C with the specified name and descriptor that is declared in a subinterface of I.
The result of method resolution is determined as follows:
If method lookup failed, method resolution throws a
NoSuchMethodError
.Otherwise, method lookup succeeded. Access control is applied for the access from D to the method which is the result of method lookup (5.4.4). Then:
If access control failed, method resolution fails for the same reason.
Otherwise, access control succeeded. Loading constraints are imposed, as follows.
Let
<
E, L1>
be the class or interface in which the referenced method m is actually declared. Let L2 be the defining loader of D.Given that the return type of m is Tr, and that the formal parameter types of m are Tf1, ..., Tfn:If Tr is not an array type, let T0 be Tr; otherwise, let T0 be the element type of Tr.For i = 1 to n: If Tfi is not an array type, let Ti be Tfi; otherwise, let Ti be the element type of Tfi.The Java Virtual Machine imposes the loading constraints TiL1 = TiL2 for i = 0 to n.For each class or interface name N mentioned by the descriptor of the referenced method (4.3.3), the Java Virtual Machine imposes the loading constraint NL1 = NL2 (5.3.4).
If imposing these constraints results in any loading constraints being violated (5.3.4), then method resolution fails. Otherwise, method resolution succeeds.
When resolution searches for a method in
thea class's superinterfaces, the best outcome is to identify a maximally-specific non-abstract
method. It is possible that this method will be chosen by method selection, so it is desirable to add class loader constraints for it.
Otherwise, the result is nondeterministic. This is not new: The Java® Virtual Machine Specification has never identified exactly which method is chosen, and how "ties" should be broken. Prior to Java SE 8, this was mostly an unobservable distinction. However, beginning with Java SE 8, the set of interface methods is more heterogenous, so care must be taken to avoid problems with nondeterministic behavior. Thus:
Superinterface methods that are
private
andstatic
are ignored by resolution. This is consistent with the Java programming language, where such interface methods are not inherited.Any behavior controlled by the resolved method should not depend on whether the method is
abstract
or not.
Note that if the result of resolution is an
abstract
method, the referenced class C may be non-abstract
. Requiring C to beabstract
would conflict with the nondeterministic choice of superinterface methods. Instead, resolution assumes that the run time class of the invoked object has a concrete implementation of the method.
5.4.3.4 Interface Method Resolution
To resolve an unresolved symbolic reference from D to an interface method in an interface C, the symbolic reference to C given by the interface method reference is first resolved (5.4.3.1). Therefore, any exception that can be thrown as a result of failure of resolution of an interface reference a reference to a class, interface, or array type can be thrown as a result of failure of interface method resolution. If the reference to C can be successfully resolved, exceptions relating to the resolution of the interface method reference itself can be thrown.
When resolving an interface method reference:
If C is not an interface, interface method resolution throws an
IncompatibleClassChangeError
.Otherwise, if C declares a method with the name and descriptor specified by the interface method reference, method lookup succeeds.
Otherwise, if the class
Object
declares a method with the name and descriptor specified by the interface method reference, which has itsACC_PUBLIC
flag set and does not have itsACC_STATIC
flag set, method lookup succeeds.Otherwise, if the maximally-specific superinterface methods (5.4.3.3) of C for the name and descriptor specified by the method reference include exactly one method that does not have its
ACC_ABSTRACT
flag set, then this method is chosen and method lookup succeeds.Otherwise, if any superinterface of C declares a method with the name and descriptor specified by the method reference that has neither its
ACC_PRIVATE
flag nor itsACC_STATIC
flag set, one of these is arbitrarily chosen and method lookup succeeds.Otherwise, method lookup fails.
The result of interface method resolution is determined as follows:
If method lookup failed, interface method resolution throws a
NoSuchMethodError
.Otherwise, method lookup succeeded. Access control is applied for the access from D to the method which is the result of method lookup (5.4.4). Then:
If access control failed, interface method resolution fails for the same reason.
Otherwise, access control succeeded. Loading constraints are imposed, as follows.
Let
<
E, L1>
be the class or interface in which the referenced interface method m is actually declared. Let L2 be the defining loader of D.Given that the return type of m is Tr, and that the formal parameter types of m are Tf1, ..., Tfn:If Tr is not an array type, let T0 be Tr; otherwise, let T0 be the element type of Tr.For i = 1 to n: If Tfi is not an array type, let Ti be Tfi; otherwise, let Ti be the element type of Tfi.The Java Virtual Machine imposes the loading constraints TiL1 = TiL2 for i = 0 to n.For each class or interface name N mentioned by the descriptor of the referenced method (4.3.3), the Java Virtual Machine imposes the loading constraint NL1 = NL2 (5.3.4).
If imposing these constraints results in any loading constraints being violated (5.3.4), then interface method resolution fails. Otherwise, interface method resolution succeeds.
Access control is necessary because interface method resolution may pick a
private
method of interface C. (Prior to Java SE 8, the result of interface method resolution could be a non-public
method of classObject
or astatic
method of classObject
; such results were not consistent with the inheritance model of the Java programming language, and are disallowed in Java SE 8 and above.)
5.4.3.5 Method Type and Method Handle Resolution
To resolve an unresolved symbolic reference to a method type, it is as if resolution occurs of unresolved symbolic references to classes and interfaces (5.4.3.1) whose names correspond to the types given in are mentioned by the method descriptor (4.3.3), in the order in which they are mentioned.
Any exception that can be thrown as a result of failure of resolution of a class reference to a class or interface can thus be thrown as a result of failure of method type resolution.
The result of successful method type resolution is a reference
to an instance of java.lang.invoke.MethodType
which represents the method descriptor.
Method type resolution occurs regardless of whether the run-time constant pool actually contains symbolic references to classes and interfaces indicated in the method descriptor. Also, the resolution is deemed to occur on unresolved symbolic references, so a failure to resolve one method type will not necessarily lead to a later failure to resolve another method type with the same textual method descriptor, if suitable classes and interfaces can be loaded by the later time.
Resolution of an unresolved symbolic reference to a method handle is more complicated. Each method handle resolved by the Java Virtual Machine has an equivalent instruction sequence called its bytecode behavior, indicated by the method handle's kind. The integer values and descriptions of the nine kinds of method handle are given in Table 5.4.3.5-A.
Symbolic references by an instruction sequence to fields or methods are indicated by C.x:T
, where x
and T
are the name and descriptor (4.3.2, 4.3.3) of the field or method, and C
is the class, or interface, or array type in which the field or method is to be found.
Table 5.4.3.5-A. Bytecode Behaviors for Method Handles
Kind | Description | Interpretation |
---|---|---|
1 | REF_getField |
getfield C.f:T |
2 | REF_getStatic |
getstatic C.f:T |
3 | REF_putField |
putfield C.f:T |
4 | REF_putStatic |
putstatic C.f:T |
5 | REF_invokeVirtual |
invokevirtual C.m:(A*)T |
6 | REF_invokeStatic |
invokestatic C.m:(A*)T |
7 | REF_invokeSpecial |
invokespecial C.m:(A*)T |
8 | REF_newInvokeSpecial |
new C; dup; invokespecial C.<init>:(A*)V |
9 | REF_invokeInterface |
invokeinterface C.m:(A*)T |
Let MH be the symbolic reference to a method handle (5.1) being resolved. Also:
Let R be the symbolic reference to
thea field or methodcontained withingiven by MH.R is derived from theCONSTANT_Fieldref
,CONSTANT_Methodref
, orCONSTANT_InterfaceMethodref
structure referred to by thereference_index
item of theCONSTANT_MethodHandle
from which MH is derived.It was already established that a symbolic reference to a method handle gives a symbolic reference to a field or method (5.1). No need to be talking about class file constructs here.
For example, R is a symbolic reference to C
.
f for bytecode behavior of kind 1, and a symbolic reference to C.
<init>
for bytecode behavior of kind 8.If MH's bytecode behavior is kind 7 (REF_invokeSpecial
), then C must be the current class or interface, a superclass of the current class, a direct superinterface of the current class or interface, orObject
.Let C be the class, interface, or array type referenced by R.
Let T be the type
ofgiven by the fieldreferenced bydescriptor of R, or the return typeofgiven by the methodreferenced bydescriptor of R. Let A* be the sequence (perhaps empty) of parameter typesofgiven by the methodreferenced bydescriptor of R.T and A* are derived from theCONSTANT_NameAndType
structure referred to by thename_and_type_index
item in theCONSTANT_Fieldref
,CONSTANT_Methodref
, orCONSTANT_InterfaceMethodref
structure from which R is derived.
To resolve MH, all symbolic references to classes, interfaces, array types, fields, and methods in MH's bytecode behavior are resolved, using the following four steps:
R is resolved. This occurs as if by field resolution (5.4.3.2) when MH's bytecode behavior is kind 1, 2, 3, or 4, and as if by method resolution (5.4.3.3) when MH's bytecode behavior is kind 5, 6, 7, or 8, and as if by interface method resolution (5.4.3.4) when MH's bytecode behavior is kind 9.
The following constraints apply to the result of resolving R. These constraints correspond to those that would be enforced during verification or execution of the instruction sequence for the relevant bytecode behavior.
If MH's bytecode behavior is kind 7 (
REF_invokeSpecial
), then C must be the current class or interface, a superclass of the current class, a direct superinterface of the current class or interface, orObject
.Moved this rule here to be clear about the timing and effects of this error check.
If MH's bytecode behavior is kind 8 (
REF_newInvokeSpecial
), then R must resolve to an instance initialization method declared in class C.If R resolves to a
protected
member, then the following rules apply depending on the kind of MH's bytecode behavior:For kinds 1, 3, and 5 (
REF_getField
,REF_putField
, andREF_invokeVirtual
): IfC.f
orC.m
resolved to aprotected
field or method, and C is a class in in a different run-time package than the current class, then C must beassignable toa subclass of the current class.If C is an array type and access checking succeeds, then we're not applying the inheritance clause and this check is not necessary. (See details about
protected
members of array types in 5.4.4.)For kind 8 (
REF_newInvokeSpecial
): If C.
<init>
resolved to aprotected
method, then C must be declared in the same run-time package as the current class.
R must resolve to a
static
or non-static
member depending on the kind of MH's bytecode behavior:For kinds 1, 3, 5, 7, and 9 (
REF_getField
,REF_putField
,REF_invokeVirtual
,REF_invokeSpecial
, andREF_invokeInterface
):C.f
orC.m
must resolve to a non-static
field or method.For kinds 2, 4, and 6 (
REF_getStatic
,REF_putStatic
, andREF_invokeStatic
):C.f
orC.m
must resolve to astatic
field or method.
Resolution occurs as if of unresolved symbolic references to classes and interfaces whose names correspond to each type in A* , and to the type T, in that order.This is phrased incorrectly—not all types correspond to class and interface names. It's also unnecessary: the next step will perform
MethodType
resolution which, as described above, resolves all the mentioned classes and interfaces.A reference to an instance of
java.lang.invoke.MethodType
is obtained as if by resolution of an unresolved symbolic reference to a method type that contains the method descriptor specified in Table 5.4.3.5-B for the kind of MH.It is as if the symbolic reference to a method handle contains a symbolic reference to the method type that the resolved method handle will eventually have. The detailed structure of the method type is obtained by inspecting Table 5.4.3.5-B.
Table 5.4.3.5-B. Method Descriptors for Method Handles
Kind Description Method descriptor 1 REF_getField
(C)T
2 REF_getStatic
()T
3 REF_putField
(C,T)V
4 REF_putStatic
(T)V
5 REF_invokeVirtual
(C,A*)T
6 REF_invokeStatic
(A*)T
7 REF_invokeSpecial
(C,A*)T
8 REF_newInvokeSpecial
(A*)C
9 REF_invokeInterface
(C,A*)T
In steps 1, 3, and 4 1 and 3, any exception that can be thrown as a result of failure of resolution of a symbolic reference to a class, interface, field, or method can be thrown as a result of failure of method handle resolution. In step 2, any failure due to the specified constraints causes a failure of method handle resolution due to an IllegalAccessError
.
The intent is that resolving a method handle can be done in exactly the same circumstances that the Java Virtual Machine would successfully verify and resolve the symbolic references in the bytecode behavior. In particular, method handles to
private
,protected
, andstatic
members can be created in exactly those classes for which the corresponding normal accesses are legal.
The result of successful method handle resolution is a reference
to an instance of java.lang.invoke.MethodHandle
which represents the method handle MH.
The type descriptor of this java.lang.invoke.MethodHandle
instance is the java.lang.invoke.MethodType
instance produced in the third step of method handle resolution above.
The type descriptor of a method handle is such that a valid call to
invokeExact
injava.lang.invoke.MethodHandle
on the method handle has exactly the same stack effects as the bytecode behavior. Calling this method handle on a valid set of arguments has exactly the same effect and returns the same result (if any) as the corresponding bytecode behavior.
If the method referenced by R has the ACC_VARARGS
flag set (4.6), then the java.lang.invoke.MethodHandle
instance is a variable arity method handle; otherwise, it is a fixed arity method handle.
A variable arity method handle performs argument list boxing (JLS §15.12.4.2) when invoked via invoke
, while its behavior with respect to invokeExact
is as if the ACC_VARARGS
flag were not set.
Method handle resolution throws an IncompatibleClassChangeError
if the method referenced by R has the ACC_VARARGS
flag set and either A* is an empty sequence or the last parameter type in A* is not an array type. That is, creation of a variable arity method handle fails.
An implementation of the Java Virtual Machine is not required to intern method types or method handles. That is, two distinct symbolic references to method types or method handles which are structurally identical might not resolve to the same instance of java.lang.invoke.MethodType
or java.lang.invoke.MethodHandle
respectively.
The
java.lang.invoke.MethodHandles
class in the Java SE Platform API allows creation of method handles with no bytecode behavior. Their behavior is defined by the method ofjava.lang.invoke.MethodHandles
that creates them. For example, a method handle may, when invoked, first apply transformations to its argument values, then supply the transformed values to the invocation of another method handle, then apply a transformation to the value returned from that invocation, then return the transformed value as its own result.
5.4.3.6 Dynamically-Computed Constant and Call Site Resolution
To resolve an unresolved symbolic reference R to a dynamically-computed constant or call site, there are three tasks. First, R is examined to determine which code will serve as its bootstrap method, and which arguments will be passed to that code. Second, the arguments are packaged into an array and the bootstrap method is invoked. Third, the result of the bootstrap method is validated, and used as the result of resolution.
The first task involves the following steps:
R gives a symbolic reference to a bootstrap method handle. The bootstrap method handle is resolved (5.4.3.5) to obtain a
reference
to an instance ofjava.lang.invoke.MethodHandle
.Any exception that can be thrown as a result of failure of resolution of a symbolic reference to a method handle can be thrown in this step.
If R is a symbolic reference to a dynamically-computed constant, then let D be the type descriptor of the bootstrap method handle. (That is, D is a
reference
to an instance ofjava.lang.invoke.MethodType
.) The first parameter type indicated by D must bejava.lang.invoke.MethodHandles.Lookup
, or else resolution fails with aBootstrapMethodError
. For historical reasons, the bootstrap method handle for a dynamically-computed call site is not similarly constrained.If R is a symbolic reference to a dynamically-computed constant, then it gives a field descriptor.
If the field descriptor indicates a primitive type, then a
reference
to the pre-definedClass
object representing that type is obtained (see the methodisPrimitive
in classClass
).Otherwise, the field descriptor indicates a class or interface type, or an array type. A
reference
to theClass
object representing the type indicated by the field descriptor is obtained, as if by resolution of an unresolved symbolic reference to a class,orinterface, or array type (5.4.3.1) whose name or descriptor corresponds to the type indicated by the field descriptor.Any exception that can be thrown as a result of failure of resolution of a symbolic reference to a class,
orinterface, or array type can be thrown in this step.If R is a symbolic reference to a dynamically-computed call site, then it gives a method descriptor.
A
reference
to an instance ofjava.lang.invoke.MethodType
is obtained, as if by resolution of an unresolved symbolic reference to a method type (5.4.3.5) with the same parameter and return types as the method descriptor.Any exception that can be thrown as a result of failure of resolution of a symbolic reference to a method type can be thrown in this step.
R gives zero or more static arguments, which communicate application-specific metadata to the bootstrap method. Each static argument A is resolved, in the order given by R, as follows:
If A is a string constant, then a
reference
to its instance of classString
is obtained.If A is a numeric constant, then a
reference
to aninstance ofobject representing the number is obtained by the following procedure:java.lang.invoke.MethodHandle
Let v be the value of the numeric constant, and let T be a field descriptor which corresponds to the type of the numeric constant.
Let MH be a method handle produced as if by invocation of the
identity
method ofjava.lang.invoke.MethodHandles
with an argument representing the classObject
.A
reference
to aninstance ofobject is obtained as if by the invocationjava.lang.invoke.MethodHandle
MH.invoke(v)
with method descriptor(T)Ljava/lang/Object;
.
This is a bug fix: the value of a static argument representing a number is a boxed number, not a
MethodHandle
!If A is a symbolic reference to a dynamically-computed constant with a field descriptor indicating a primitive type T, then A is resolved, producing a primitive value v. Given v and T, a
reference
is obtained to aninstance ofobject encoding v according to the procedure specified above for numeric constants.java.lang.invoke.MethodHandle
If A is any other kind of symbolic reference, then the result is the result of resolving A.
Among the symbolic references in the run-time constant pool, symbolic references to dynamically-computed constants are special because they are derived from
constant_pool
entries that can syntactically refer to themselves via theBootstrapMethods
attribute (4.7.23). However, the Java Virtual Machine does not support resolving a symbolic reference to a dynamically-computed constant that depends on itself (that is, as a static argument to its own bootstrap method). Accordingly, when both R and A are symbolic references to dynamically-computed constants, if A is the same as R or A gives a static argument that (directly or indirectly) references R, then resolution fails with aStackOverflowError
at the point where re-resolution of R would be required.Unlike class initialization (5.5), where cycles are allowed between uninitialized classes, resolution does not allow cycles in symbolic references to dynamically-computed constants. If an implementation of resolution makes recursive use of a stack, then a
StackOverflowError
will occur naturally. If not, the implementation is required to detect the cycle rather than, say, looping infinitely or returning a default value for the dynamically-computed constant.A similar cycle may arise if the body of a bootstrap method makes reference to a dynamically-computed constant currently being resolved. This has always been possible for invokedynamic bootstraps, and does not require special treatment in resolution; the recursive
invokeWithArguments
calls will naturally lead to aStackOverflowError
.Any exception that can be thrown as a result of failure of resolution of a symbolic reference can be thrown in this step.
The second task, to invoke the bootstrap method handle, involves the following steps:
An array is allocated with component type
Object
and length n+3, where n is the number of static arguments given by R (n ≥ 0).The zeroth component of the array is set to a
reference
to an instance ofjava.lang.invoke.MethodHandles.Lookup
for the class in which R occurs, produced as if by invocation of thelookup
method ofjava.lang.invoke.MethodHandles
.The first component of the array is set to a
reference
to an instance ofString
that denotes N, the unqualified name given by R.The second component of the array is set to the
reference
to an instance ofClass
orjava.lang.invoke.MethodType
that was obtained earlier for the field descriptor or method descriptor given by R.Subsequent components of the array are set to the
reference
s that were obtained earlier from resolving R's static arguments, if any. Thereference
s appear in the array in the same order as the corresponding static arguments are given by R.A Java Virtual Machine implementation may be able to skip allocation of the array and, without any change in observable behavior, pass the arguments directly to the bootstrap method.
The bootstrap method handle is invoked, as if by the invocation
BMH.invokeWithArguments(args)
, whereBMH
is the bootstrap method handle andargs
is the array allocated above.Due to the behavior of the
invokeWithArguments
method ofjava.lang.invoke.MethodHandle
, the type descriptor of the bootstrap method handle need not exactly match the run-time types of the arguments. For example, the second parameter type of the bootstrap method handle (corresponding to the unqualified name given in the first component of the array above) could beObject
instead ofString
. If the bootstrap method handle is variable arity, then some or all of the arguments may be collected into a trailing array parameter.The invocation occurs within a thread that is attempting resolution of this symbolic reference. If there are several such threads, the bootstrap method handle may be invoked concurrently. Bootstrap methods which access global application data should take the usual precautions against race conditions.
If the invocation fails by throwing an instance of
Error
or a subclass ofError
, resolution fails with that exception.If the invocation fails by throwing an exception that is not an instance of
Error
or a subclass ofError
, resolution fails with aBootstrapMethodError
whose cause is the thrown exception.If several threads concurrently invoke the bootstrap method handle for this symbolic reference, the Java Virtual Machine chooses the result of one invocation and installs it visibly to all threads. Any other bootstrap methods executing for this symbolic reference are allowed to complete, but their results are ignored.
The third task, to validate the reference
, o, produced by invocation of the bootstrap method handle, is as follows:
If R is a symbolic reference to a dynamically-computed constant, then o is converted to type T, the type indicated by the field descriptor given by R.
o's conversion occurs as if by the invocation
MH.invoke(o)
with method descriptor(Ljava/lang/Object;)T
, where MH is a method handle produced as if by invocation of theidentity
method ofjava.lang.invoke.MethodHandles
with an argument representing the classObject
.The result of o's conversion is the result of resolution.
If the conversion fails by throwing a
NullPointerException
or aClassCastException
, resolution fails with aBootstrapMethodError
.If R is a symbolic reference to a dynamically-computed call site, then o is the result of resolution if it has all of the following properties:
o is not
null
.o is an instance of
java.lang.invoke.CallSite
or a subclass ofjava.lang.invoke.CallSite
.The type of the
java.lang.invoke.CallSite
is semantically equal to the method descriptor given by R.
If o does not have these properties, resolution fails with a
BootstrapMethodError
.
Many of the steps above perform computations "as if by invocation" of certain methods. In each case, the invocation behavior is given in detail by the specifications for invokestatic and invokevirtual. The invocation occurs in the thread and from the class that is attempting resolution of the symbolic reference R. However, no corresponding method references are required to appear in the run-time constant pool, no particular method's operand stack is necessarily used, and the value of the max_stack
item of any method's Code
attribute is not enforced for the invocation.
If several threads attempt resolution of R at the same time, the bootstrap method may be invoked concurrently. Therefore, bootstrap methods which access global application data must take precautions against race conditions.
This was stated already, at the end of step 2.
5.4.4 Access Control
Access control is applied during resolution (5.4.3) to ensure that a reference to a class, interface, field, or method is permitted. Access control succeeds if a specified class, interface, field, or method is accessible to the referring class or interface.
A class or interface C is accessible to a class or interface D if and only if one of the following is true:
C is
public
, and a member of the same run-time module as D (5.3.6).C is
public
, and a member of a different run-time module than D, and C's run-time module is read by D's run-time module, and C's run-time module exports C's run-time package to D's run-time module.C is not
public
, and C and D are members of the same run-time package.
If C is not accessible to D, access control throws an IllegalAccessError
. Otherwise, access control succeeds.
A field or method R is accessible to a class or interface D if and only if any of the following is true:
R is
public
.R is the method
Object.clone()
and the symbolic reference to R contains a symbolic reference to an array type.The
Object.clone
method isprotected
, but is treated by access checking as if it had been overridden by apublic
method in every array type.R is
protected
and is declared in a class C, and D iseithera subclass of Cor C itself.The same-package clause, below, handles the case where C = D. No need to complicate this rule.
Furthermore, if R is not
static
, then the symbolic reference to R must contain a symbolic reference to a class T, such that T is either a subclass of D, a superclass of D, or D itself.If the reference is to a protected member of an array type—specifically,
Object.finalize
—then the array type could be considered a "subclass of" the current class, if the current class isObject
. But in that case, the same-package clause applies, so there is no need to handle the array type here.During verification of D, it was required that, even if T is a superclass of D, the target reference of a
protected
field access or method invocation must be an instance of D or a subclass of D (4.10.1.8).R is either
protected
or has default access (that is, neitherpublic
norprotected
norprivate
), and is declared by a class in the same run-time package as D.R is
private
and is declared by a class or interface C that belongs to the same nest as D, according to the nestmate test below.
If R is not accessible to D, then:
If R is
public
,protected
, or has default access, then access control throws anIllegalAccessError
.If R is
private
, then the nestmate test failed, and access control fails for the same reason.
Otherwise, access control succeeds.
A nest is a set of classes and interfaces that allow mutual access to their private
members. One of the classes or interfaces is the nest host. It enumerates the classes and interfaces which belong to the nest, using the NestMembers
attribute (4.7.29). Each of them in turn designates it as the nest host, using the NestHost
attribute (4.7.28). A class or interface which lacks a NestHost
attribute belongs to the nest hosted by itself; if it also lacks a NestMembers
attribute, this nest is a singleton consisting only of the class or interface itself.
To determine whether a class or interface C belongs to the same nest as a class or interface D, the nestmate test is applied. C and D belong to the same nest if and only if the nestmate test succeeds. The nestmate test is as follows:
If C and D are the same class or interface, then the nestmate test succeeds.
Otherwise, the following steps are performed, in order:
The nest host of D, H, is determined (below). If an exception is thrown, then the nestmate test fails for the same reason.
The nest host of C, H', is determined (below). If an exception is thrown, then the nestmate test fails for the same reason.
H and H' are compared. If H and H' are the same class or interface, then the nestmate test succeeds. Otherwise, the nestmate test fails by throwing an
IllegalAccessError
.
The nest host of a class or interface M is determined as follows:
If M lacks a
NestHost
attribute, then M is its own nest host.Otherwise, M has a
NestHost
attribute, and itshost_class_index
item is used as an index into the run-time constant pool of M. The symbolic reference at that index is resolved to a class,orinterface, or array type H (5.4.3.1).During resolution of this symbolic reference, any of the exceptions pertaining to class or interface resolution can be thrown. Otherwise, resolution of H succeeds.
If any of the following is true, an
IncompatibleClassChangeError
is thrown:H is an array type.
H is not in the same run-time package as M.
H lacks a
NestMembers
attribute.H has a
NestMembers
attribute, but there is no entry in itsclasses
array that refers to a class or interface with the name N, where N is the name of M.
Otherwise, H is the nest host of M.
Actual implementation behavior: Hotspot and OpenJ9 both report access control failures when the host class is an array type. So no change in behavior is required. But the error messages are confusing, suggesting that the array type belongs to the wrong package or lacks a
NestMembers
attribute.
5.4.6 Method Selection
During execution of an invokeinterface or invokevirtual instruction, a method is selected with respect to (i) the run-time type of the object on the stack, and (ii) a method that was previously resolved by the instruction. The rules to select a method with respect to a class, or interface, or array type C and a method mR are as follows:
If mR is marked
ACC_PRIVATE
, then it is the selected method.Otherwise, the selected method is determined by the following lookup procedure:
If C is a class or interface that contains a declaration of an instance method m that can override mR (5.4.5), then m is the selected method.
Otherwise, if C is a class and has a superclass, a search for a declaration of an instance method that can override mR is performed, starting with the direct superclass of C and continuing with the direct superclass of that class, and so forth, until a method is found or no further superclasses exist. If a method is found, it is the selected method.
Otherwise, if C is an interface or an array type and the class
Object
declares a method that can override mR, the method declared byObject
is the selected method.Otherwise, the maximally-specific superinterface methods of C are determined (5.4.3.3). If exactly one matches mR's name and descriptor and is not
abstract
, then it is the selected method.Any maximally-specific superinterface method selected in this step can override mR; there is no need to check this explicitly.
While C will typically be a class or an array type, it may be an interface when these rules are applied during preparation (5.4.2).
5.5 Initialization
Initialization of a class or interface consists of executing its class or interface initialization method (2.9.2).
A class or interface C may be initialized only as a result of:
The execution of any one of the Java Virtual Machine instructions new, getstatic, putstatic, or invokestatic that references C (6.5.new, 6.5.getstatic, 6.5.putstatic, 6.5.invokestatic).
Upon execution of a new instruction, the class to be initialized is the class referenced by the instruction.
Upon execution of a getstatic, putstatic, or invokestatic instruction, the class or interface to be initialized is the class or interface that declares the resolved field or method.
The first invocation of a
java.lang.invoke.MethodHandle
instance which was the result of method handle resolution (5.4.3.5) for a method handle of kind 2 (REF_getStatic
), 4 (REF_putStatic
), 6 (REF_invokeStatic
), or 8 (REF_newInvokeSpecial
).This implies that the class of a bootstrap method is initialized when the bootstrap method is invoked for an invokedynamic instruction (6.5.invokedynamic), as part of the continuing resolution of the call site specifier.
Invocation of certain reflective methods in the class library (2.12), for example, in class
Class
or in packagejava.lang.reflect
.If C is a class, the initialization of one of its subclasses.
If C is an interface that declares a non-
abstract
, non-static
method, the initialization of a class that implements C directly or indirectly.Its designation as the initial class or interface at Java Virtual Machine startup (5.2).
Prior to initialization, a class or interface must be linked, that is, verified, prepared, and optionally resolved.
Because the Java Virtual Machine is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time. There is also the possibility that initialization of a class or interface may be requested recursively as part of the initialization of that class or interface. The implementation of the Java Virtual Machine is responsible for taking care of synchronization and recursive initialization by using the following procedure. It assumes that the class or interface has already been verified and prepared, and that the Class
object class or interface contains state that indicates one of four situations:Class
object
This
class or interface is verified and prepared but not initialized.Class
objectThis
class or interface is being initialized by some particular thread.Class
objectThis
class or interface is fully initialized and ready for use.Class
objectThis
class or interface is in an erroneous state, perhaps because initialization was attempted and failed.Class
object
Here and below, we eliminate the unnecessary assertion that the initialization state of the class is stored by an instance of java.lang.Class
. The specification need not concern itself with how classes are internally represented and how this representation relates to instances of java.lang.Class
.
For each class or interface C, there is a unique initialization lock LC. The mapping from C to LC is left to the discretion of the Java Virtual Machine implementation. For example, LC could be the Class
object for C, or the monitor associated with that Class
object. The procedure for initializing C is then as follows:
Synchronize on the initialization lock, LC, for C. This involves waiting until the current thread can acquire LC.
If
theC indicates that initialization is in progress for C by some other thread, then release LC and block the current thread until informed that the in-progress initialization has completed, at which time repeat this procedure.Class
object forThread interrupt status is unaffected by execution of the initialization procedure.
If
theC indicates that initialization is in progress for C by the current thread, then this must be a recursive request for initialization. Release LC and complete normally.Class
object forIf
theC indicates thatClass
object forCit has already been initialized, then no further action is required. Release LC and complete normally.If
theC is in an erroneous state, then initialization is not possible. Release LC and throw aClass
object forNoClassDefFoundError
.Otherwise, record the fact that initialization of the
Class
object for C is in progress by the current thread, and release LC.Then, initialize each
final
static
field of C with the constant value in itsConstantValue
attribute (4.7.2), in the order the fields appear in theClassFile
structure.Next, if C is a class rather than an interface, then let SC be its superclass and let SI1, ..., SIn be all superinterfaces of C (whether direct or indirect) that declare at least one non-
abstract
, non-static
method. The order of superinterfaces is given by a recursive enumeration over the superinterface hierarchy of each interface directly implemented by C. For each interface I directly implemented by C (in the order of theinterfaces
array of C), the enumeration recurs on I's superinterfaces (in the order of theinterfaces
array of I) before returning I.For each S in the list [ SC, SI1, ..., SIn ], if S has not yet been initialized, then recursively perform this entire procedure for S. If necessary, verify and prepare S first.
If the initialization of S completes abruptly because of a thrown exception, then acquire LC, label
theC as erroneous, notify all waiting threads, release LC, and complete abruptly, throwing the same exception that resulted from initializingClass
object forSCS.Next, determine whether assertions are enabled for C by querying its defining class loader.
Next, if C declares a class or interface initialization method, execute that method.
If the execution of the class or interface initialization method completes normally, then acquire LC, label the
Class
object for C as fully initialized, notify all waiting threads, release LC, and complete this procedure normally.Otherwise, the class or interface initialization method must have completed abruptly by throwing some exception E. If the class of E is not
Error
or one of its subclasses, then create a new instance of the classExceptionInInitializerError
with E as the argument, and use this object in place of E in the following step. If a new instance ofExceptionInInitializerError
cannot be created because anOutOfMemoryError
occurs, then use anOutOfMemoryError
object in place of E in the following step.Acquire LC, label
theC as erroneous, notify all waiting threads, release LC, and complete this procedure abruptly with reason E or its replacement as determined in the previous step.Class
object for
A Java Virtual Machine implementation may optimize this procedure by eliding the lock acquisition in step 1 (and release in step 4/5) when it can determine that the initialization of the class has already completed, provided that, in terms of the Java memory model, all happens-before orderings (JLS §17.4.5) that would exist if the lock were acquired, still exist when the optimization is performed.
Chapter 6: The Java Virtual Machine Instruction Set
6.5 Instructions
aastore
- Operation
Store into
reference
array- Format
aastore
- Forms
aastore = 83 (0x53)
- Operand Stack
..., arrayref, index, value →
...
- Description
The arrayref must be of type
reference
and must refer to an array whose components are of typereference
. The index must be of typeint
, and value must be of typereference
. The arrayref, index, and value are popped from the operand stack.If value is
null
, then value is stored as the component of the array at index.Otherwise, value is non-
null
.If the type of value is assignment compatible with the type of the components of the array referenced by arrayref, then value is stored as the component of the array at index.If value is a value of the component type of the array referenced by arrayref, then value is stored as the component of the array at index.The following rules are used to determine whether a value that is not
null
is assignment compatible with the array component type. If S is the type of the object referred to by value, and T is the reference type of the array components, then aastore determines whether assignment is compatible as follows:If S is a class type, then:
If T is a class type, then S must be the same class as T, or S must be a subclass of T;
If T is an interface type, then S must implement interface T.
If S is an array type SC
[]
, that is, an array of components of type SC, then:If T is a class type, then T must be
Object
.If T is an interface type, then T must be one of the interfaces implemented by arrays (JLS §4.10.3).
If T is an array type TC
[]
, that is, an array of components of type TC, then one of the following must be true:TC and SC are the same primitive type.
TC and SC are reference types, and type SC is assignable to TC by these run-time rules.
Whether value is a value of the array component type is determined according to the rules given for checkcast.
Appealing to "assignment compatible" is a roundabout way to say what we really mean—value must be a value of the array's component type.
aastore, checkcast, and instanceof use the same rules to interpret types. It's helpful to consolidate those rules in one place, so that readers can clearly see that the rules are the same, and so that future enhancements to the type system have fewer rules to maintain.
- Run-time Exceptions
If arrayref is
null
, aastore throws aNullPointerException
.Otherwise, if index is not within the bounds of the array referenced by arrayref, the aastore instruction throws an
ArrayIndexOutOfBoundsException
.Otherwise, if
arrayref is notthe non-null
and the actual type ofnull
value is notassignment compatible with the actual type of the components of the arraya value of the array component type, aastore throws anArrayStoreException
."Otherwise" here implies "arrayref is not
null
".
anewarray
- Operation
Create new array of
reference
- Format
anewarray
indexbyte1
indexbyte2- Forms
anewarray = 189 (0xbd)
- Operand Stack
..., count →
..., arrayref
- Description
The count must be of type
int
. It is popped off the operand stack. The count represents the number of components of the array to be created. The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a class,array, or interface typeinterface, or array type. The named class,array, or interface typeinterface, or array type is resolved (5.4.3.1). A new array withcomponents of that typecomponent type given by the resolved class, interface, or array type, of length count, is allocated from the garbage-collected heap, and areference
arrayref to this new array object is pushed onto the operand stack. All components of the new array are initialized tonull
, the default value forreference
types (2.4).- Linking Exceptions
During resolution of the symbolic reference to the class,
array, or interface typeinterface, or array type, any of the exceptions documented in 5.4.3.1 can be thrown.- Run-time Exceptions
Otherwise, if count is less than zero, the anewarray instruction throws a
NegativeArraySizeException
.- Notes
The anewarray instruction is used to create a single dimension of an array of object references or part of a multidimensional array.
checkcast
- Operation
Check whether object is of given type
- Format
checkcast
indexbyte1
indexbyte2- Forms
checkcast = 192 (0xc0)
- Operand Stack
..., objectref →
..., objectref
- Description
The objectref must be of type
reference
. The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a class,array, or interface typeinterface, or array type.If objectref is
null
, then the operand stack is unchanged.Otherwise, the named class,
array, or interface typeinterface, or array type is resolved (5.4.3.1). If objectrefcan be cast to the resolved class, array, or interface typeis a value of the type given by the resolved class, interface, or array type, the operand stack is unchanged; otherwise, the checkcast instruction throws a.ClassCastException
The following rules are used to determine whether
an objectref that is nota reference to an object is a value of a reference type, T.null
can be cast to the resolved typeIf S is the type of the object referred to by objectref, and T is the resolved class, array, or interface type, then checkcast determines whether objectref can be cast to type T as follows:If
S is a class typethe reference is to an instance of a class C, then:If T is a class type, then S must be the same class as T, or S must be a subclass of T;If T is the type of a class D, then the reference is a value of T if C is D or a subclass of D.
If T is an interface type, then S must implement interface T.If T is the type of an interface I, then the reference is a value of T if C implements I.
If
S is an array type SCthe reference is to an array with component type SC, then:[]
, that is, an array of components of type SCIf T is a class type, then
T must bethe reference is a value of T if T isObject
Object
.If T is an interface type, then
T must be one of the interfaces implemented by arrays (JLS §4.10.3)the reference is a value of T if T isCloneable
orjava.io.Serializable
(as loaded by the bootstrap class loader).It's unnecessary and especially risky to tie JVMS to the Java Language Specification here—we certainly don't want language changes to accidentally impact the routine behavior of JVM instructions.
If T is an array type TC
[]
, that is, an array of components of type TC, thenone of the following must be truethe reference is a value of T if one of the following are true:TC and SC are the same
primitivetype.TC and SC are reference types, and type SC can be cast to TC by recursive application of these rules.Bug fix: an earlier cleanup of these rules (JDK-8069130) removed cases to handle an interface type S. These cases appeared vacuous at the top level, but were necessary to support a recursive analysis for array types. Rather than restoring the old rules, it's probably easier to follow if the recursion is contained within the array type discussion.
Further, recursion to the top level is no longer a good fit, because the rules are expressed in terms of a specific reference, not types.
TC is the class type
Object
.TC is a class type, SC is a class type, and the class of SC is a subclass of the class of TC.
TC is an interface type, SC is a class type, and the class of SC implements the interface of TC.
TC is an interface type, SC is an interface type, and the interface of SC extends the interface of TC.
TC is the interface type
Cloneable
orjava.io.Serializable
(as loaded by the bootstrap class loader), and SC is an array type.TC is an array type TCC
[]
, SC is an array type SCC[]
, and one of these tests of array component types apply recursively to TCC and SCC.
- Linking Exceptions
During resolution of the symbolic reference to the class,
array, or interface typeinterface, or array type, any of the exceptions documented in 5.4.3.1 can be thrown.- Run-time Exception
Otherwise, if objectref
cannot be cast to the resolved class, array, or interface typeis not null and is not a value of the type given by the resolved class, interface, or array type, the checkcast instruction throws aClassCastException
.- Notes
The checkcast instruction is very similar to the instanceof instruction (6.5.instanceof). It differs in its treatment of
null
, its behavior when its test fails (checkcast throws an exception, instanceof pushes a result code), and its effect on the operand stack.
getfield
- Operation
Fetch field from object
- Format
getfield
indexbyte1
indexbyte2- Forms
getfield = 180 (0xb4)
- Operand Stack
..., objectref →
..., value
- Description
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1
<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a field (5.1), which gives the name and descriptor of the field as well as a symbolic reference to the class, interface, or array type in which the field is to be found. The referenced field is resolved (5.4.3.2).The objectref, which must be of type
reference
but not an array type, is popped from the operand stack. The value of the referenced field in objectref is fetched and pushed onto the operand stack.- Linking Exceptions
During resolution of the symbolic reference to the field, any of the errors pertaining to field resolution (5.4.3.2) can be thrown.
Otherwise, if the resolved field is a
static
field, getfield throws anIncompatibleClassChangeError
.- Run-time Exception
Otherwise, if objectref is
null
, the getfield instruction throws aNullPointerException
.- Notes
The getfield instruction cannot be used to access the
length of an array. The arraylength instruction (6.5.arraylength) is used instead.length
field
getstatic
- Operation
Get
static
field from class- Format
getstatic
indexbyte1
indexbyte2- Forms
getstatic = 178 (0xb2)
- Operand Stack
..., →
..., value
- Description
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1
<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a field (5.1), which gives the name and descriptor of the field as well as a symbolic reference to the class,orinterface, or array type in which the field is to be found. The referenced field is resolved (5.4.3.2).On successful resolution of the field, the class or interface that declared the resolved field is initialized if that class or interface has not already been initialized (5.5).
The value of the class or interface field is fetched and pushed onto the operand stack.
- Linking Exceptions
During resolution of the symbolic reference to the
class or interfacefield, any of the exceptions pertaining to field resolution (5.4.3.2) can be thrown.Otherwise, if the resolved field is not a
static
(class)fieldor an interface field, getstatic throws anIncompatibleClassChangeError
.- Run-time Exception
Otherwise, if execution of this getstatic instruction causes initialization of the
referenceddeclaring class or interface, getstatic may throw anError
as detailed in 5.5.
instanceof
- Operation
Determine if object is of given type
- Format
instanceof
indexbyte1
indexbyte2- Forms
instanceof = 193 (0xc1)
- Operand Stack
..., objectref →
..., result
- Description
The objectref, which must be of type
reference
, is popped from the operand stack. The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a class,array, or interface typeinterface, or array type.If objectref is
null
, the instanceof instruction pushes anint
result of 0as anonto the operand stack.int
Otherwise, the named class,
array, or interface typeinterface, or array type is resolved (5.4.3.1). If objectref isan instance ofa value of the type given by the resolved class, interface, or array type,or implements the resolved interface,the instanceof instruction pushes anint
result of 1as anonto the operand stack; otherwise, it pushes anint
int
result of 0.The following rules are used to determine whether an objectref that is not
null
is an instance of the resolved type. If S is the type of the object referred to by objectref, and T is the resolved class, array, or interface type, then instanceof determines whether objectref is an instance of T as follows:If S is a class type, then:
If T is a class type, then S must be the same class as T, or S must be a subclass of T;
If T is an interface type, then S must implement interface T.
If S is an array type SC
[]
, that is, an array of components of type SC, then:If T is a class type, then T must be
Object
.If T is an interface type, then T must be one of the interfaces implemented by arrays (JLS §4.10.3).
If T is an array type TC
[]
, that is, an array of components of type TC, then one of the following must be true:TC and SC are the same primitive type.
TC and SC are reference types, and type SC can be cast to TC by these run-time rules.
Whether objectref is a value of the type given by the resolved class, interface, or array type is determined according to the rules given for checkcast.
aastore, checkcast, and instanceof use the same rules to interpret types. It's helpful to consolidate those rules in one place, so that readers can clearly see that the rules are the same, and so that future enhancements to the type system have fewer rules to maintain.
- Linking Exceptions
During resolution of the symbolic reference to the class,
array, or interface typeinterface, or array type, any of the exceptions documented in 5.4.3.1 can be thrown.- Notes
The instanceof instruction is very similar to the checkcast instruction (6.5.checkcast). It differs in its treatment of
null
, its behavior when its test fails (checkcast throws an exception, instanceof pushes a result code), and its effect on the operand stack.
invokeinterface
- Operation
Invoke interface method
- Format
invokeinterface
indexbyte1
indexbyte2
count
0- Forms
invokeinterface = 185 (0xb9)
- Operand Stack
..., objectref, [arg1, [arg2 ...]] →
...
- Description
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1
<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to an interface method (5.1), which gives the name and descriptor (4.3.3) of theinterfacemethod as well as a symbolic reference to the class, interface, or array type in which the interface method is to be found. The named interface method is resolved (5.4.3.4).The resolved interface method must not be an instance initialization method, or
thea class or interface initialization method (2.9.1, 2.9.2).The count operand is an unsigned byte that must not be zero. The objectref must be of type
reference
and must be followed on the operand stack by nargs argument values, where the number, type, and order of the values must be consistent with the descriptor of the resolved interface method. The value of the fourth operand byte must always be zero.Let C be the class or array type of objectref. A method is selected with respect to C and the resolved method (5.4.6). This is the method to be invoked.
If the method to be invoked is
synchronized
, the monitor associated with objectref is entered or reentered as if by execution of a monitorenter instruction (6.5.monitorenter) in the current thread.If the method to be invoked is not
native
, the nargs argument values and objectref are popped from the operand stack. A new frame is created on the Java Virtual Machine stack for the method being invoked. The objectref and the argument values are consecutively made the values of local variables of the new frame, with objectref in local variable 0, arg1 in local variable 1 (or, if arg1 is of typelong
ordouble
, in local variables 1 and 2), and so on. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being stored in a local variable. The new frame is then made current, and the Java Virtual Machinepc
is set to the opcode of the first instruction of the method to be invoked. Execution continues with the first instruction of the method.If the method to be invoked is
native
and the platform-dependent code that implements it has not yet been bound (5.6) into the Java Virtual Machine, then that is done. The nargs argument values and objectref are popped from the operand stack and are passed as parameters to the code that implements the method. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being passed as a parameter. The parameters are passed and the code is invoked in an implementation-dependent manner. When the platform-dependent code returns:If the
native
method issynchronized
, the monitor associated with objectref is updated and possibly exited as if by execution of a monitorexit instruction (6.5.monitorexit) in the current thread.If the
native
method returns a value, the return value of the platform-dependent code is converted in an implementation-dependent way to the return type of thenative
method and pushed onto the operand stack.
- Linking Exceptions
During resolution of the symbolic reference to the interface method, any of the exceptions pertaining to interface method resolution (5.4.3.4) can be thrown.
Otherwise, if the resolved method is
static
, the invokeinterface instruction throws anIncompatibleClassChangeError
.Note that invokeinterface may refer to
private
methods declared in interfaces, including nestmate interfaces.- Run-time Exceptions
Otherwise, if objectref is
null
, the invokeinterface instruction throws aNullPointerException
.Otherwise, if the class or array type of objectref does not implement the resolved interface, invokeinterface throws an
IncompatibleClassChangeError
.Otherwise, if the selected method is neither
public
norprivate
, invokeinterface throws anIllegalAccessError
.Otherwise, if the selected method is
abstract
, invokeinterface throws anAbstractMethodError
.Otherwise, if the selected method is
native
and the code that implements the method cannot be bound, invokeinterface throws anUnsatisfiedLinkError
.Otherwise, if no method is selected, and there are multiple maximally-specific superinterface methods of C that match the resolved method's name and descriptor and are not
abstract
, invokeinterface throws anIncompatibleClassChangeError
.Otherwise, if no method is selected, and there are no maximally-specific superinterface methods of C that match the resolved method's name and descriptor and are not
abstract
, invokeinterface throws anAbstractMethodError
.- Notes
The count operand of the invokeinterface instruction records a measure of the number of argument values, where an argument value of type
long
or typedouble
contributes two units to the count value and an argument of any other type contributes one unit. This information can also be derived from the descriptor of the selected method. The redundancy is historical.The fourth operand byte exists to reserve space for an additional operand used in certain of Oracle's Java Virtual Machine implementations, which replace the invokeinterface instruction by a specialized pseudo-instruction at run time. It must be retained for backwards compatibility.
The nargs argument values and objectref are not one-to-one with the first nargs+1 local variables. Argument values of types
long
anddouble
must be stored in two consecutive local variables, thus more than nargs local variables may be required to pass nargs argument values to the invoked method.The selection logic allows a non-
abstract
method declared in a superinterface to be selected. Methods in interfaces are only considered if there is no matching method in the class hierarchy. In the event that there are two non-abstract
methods in the superinterface hierarchy, with neither more specific than the other, an error occurs; there is no attempt to disambiguate (for example, one may be the referenced method and one may be unrelated, but we do not prefer the referenced method). On the other hand, if there are manyabstract
methods but only one non-abstract
method, the non-abstract
method is selected (unless anabstract
method is more specific).
invokespecial
- Operation
Invoke instance method; direct invocation of instance initialization methods and methods of the current class and its supertypes
- Format
invokespecial
indexbyte1
indexbyte2- Forms
invokespecial = 183 (0xb7)
- Operand Stack
..., objectref, [arg1, [arg2 ...]] →
...
- Description
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1
<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a method or an interface method (5.1), which gives the name and descriptor (4.3.3) of the methodor interface methodas well as a symbolic reference to the class,orinterface, or array type in which the method or interface method is to be found. The named method is resolved (5.4.3.3, 5.4.3.4).The symbolic reference must reference a class or interface.
If the symbolic reference names a class (not an interface), and the resolved method is not an instance initialization method (2.9.1), let C be the direct superclass of the current class.
Otherwise, let C be the class or interface named by the symbolic reference.The actual method to be invoked is selected by the following lookup procedure:
If C contains a declaration for an instance method with the same name and descriptor as the resolved method, then it is the method to be invoked.
Otherwise, if C is a class and has a superclass, a search for a declaration of an instance method with the same name and descriptor as the resolved method is performed, starting with the direct superclass of C and continuing with the direct superclass of that class, and so forth, until a match is found or no further superclasses exist. If a match is found, then it is the method to be invoked.
Otherwise, if C is an interface and the class
Object
contains a declaration of apublic
instance method with the same name and descriptor as the resolved method, then it is the method to be invoked.Otherwise, if there is exactly one maximally-specific method (5.4.3.3) in the superinterfaces of C that matches the resolved method's name and descriptor and is not
abstract
, then it is the method to be invoked.
The objectref must be of type
reference
and must be followed on the operand stack by nargs argument values, where the number, type, and order of the values must be consistent with the descriptor of the selected instance method.If the method is
synchronized
, the monitor associated with objectref is entered or reentered as if by execution of a monitorenter instruction (6.5.monitorenter) in the current thread.If the method is not
native
, the nargs argument values and objectref are popped from the operand stack. A new frame is created on the Java Virtual Machine stack for the method being invoked. The objectref and the argument values are consecutively made the values of local variables of the new frame, with objectref in local variable 0, arg1 in local variable 1 (or, if arg1 is of typelong
ordouble
, in local variables 1 and 2), and so on. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being stored in a local variable. The new frame is then made current, and the Java Virtual Machinepc
is set to the opcode of the first instruction of the method to be invoked. Execution continues with the first instruction of the method.If the method is
native
and the platform-dependent code that implements it has not yet been bound (5.6) into the Java Virtual Machine, that is done. The nargs argument values and objectref are popped from the operand stack and are passed as parameters to the code that implements the method. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being passed as a parameter. The parameters are passed and the code is invoked in an implementation-dependent manner. When the platform-dependent code returns, the following take place:If the
native
method issynchronized
, the monitor associated with objectref is updated and possibly exited as if by execution of a monitorexit instruction (6.5.monitorexit) in the current thread.If the
native
method returns a value, the return value of the platform-dependent code is converted in an implementation-dependent way to the return type of thenative
method and pushed onto the operand stack.
- Linking Exceptions
During resolution of the symbolic reference to the method, any of the exceptions pertaining to method resolution (5.4.3.3) can be thrown.
Otherwise, if the resolved method is an instance initialization method, and the class in which it is declared is not the class, interface, or array type symbolically referenced by the instruction, a
NoSuchMethodError
is thrown.Otherwise, if the resolved method is a
class (static
)method, the invokespecial instruction throws anIncompatibleClassChangeError
.- Run-time Exceptions
Otherwise, if objectref is
null
, the invokespecial instruction throws aNullPointerException
.Otherwise, if step 1, step 2, or step 3 of the lookup procedure selects an
abstract
method, invokespecial throws anAbstractMethodError
.Otherwise, if step 1, step 2, or step 3 of the lookup procedure selects a
native
method and the code that implements the method cannot be bound, invokespecial throws anUnsatisfiedLinkError
.Otherwise, if step 4 of the lookup procedure determines there are multiple maximally-specific superinterface methods of C that match the resolved method's name and descriptor and are not
abstract
, invokespecial throws anIncompatibleClassChangeError
Otherwise, if step 4 of the lookup procedure determines there are no maximally-specific superinterface methods of C that match the resolved method's name and descriptor and are not
abstract
, invokespecial throws anAbstractMethodError
.- Notes
The difference between the invokespecial instruction and the invokevirtual instruction (6.5.invokevirtual) is that invokevirtual invokes a method based on the class of the object. The invokespecial instruction is used to directly invoke instance initialization methods (2.9.1) as well as methods of the current class and its supertypes.
The invokespecial instruction was named
invokenonvirtual
prior to JDK release 1.0.2.The nargs argument values and objectref are not one-to-one with the first nargs+1 local variables. Argument values of types
long
anddouble
must be stored in two consecutive local variables, thus more than nargs local variables may be required to pass nargs argument values to the invoked method.The invokespecial instruction handles invocation of a non-
abstract
interface method, referenced either via a direct superinterface or via a superclass. In these cases, the rules for selection are essentially the same as those for invokeinterface (except that the search starts from a different class).
invokestatic
- Operation
Invoke a
class (static
)method- Format
invokestatic
indexbyte1
indexbyte2- Forms
invokestatic = 184 (0xb8)
- Operand Stack
..., [arg1, [arg2 ...]] →
...
- Description
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1
<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a method or an interface method (5.1), which gives the name and descriptor (4.3.3) of the methodor interface methodas well as a symbolic reference to the class,orinterface, or array type in which the method or interface method is to be found. The named method is resolved (5.4.3.3, 5.4.3.4).The resolved method must not be an instance initialization method, or
thea class or interface initialization method (2.9.1, 2.9.2).The resolved method must be
static
, and therefore cannot beabstract
.On successful resolution of the method, the class or interface that declared the resolved method is initialized if that class or interface has not already been initialized (5.5).
The operand stack must contain nargs argument values, where the number, type, and order of the values must be consistent with the descriptor of the resolved method.
If the method is
synchronized
, the monitor associated with the resolvedClass
object is entered or reentered as if by execution of a monitorenter instruction (6.5.monitorenter) in the current thread.If the method is not
native
, the nargs argument values are popped from the operand stack. A new frame is created on the Java Virtual Machine stack for the method being invoked. The nargs argument values are consecutively made the values of local variables of the new frame, with arg1 in local variable 0 (or, if arg1 is of typelong
ordouble
, in local variables 0 and 1) and so on. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being stored in a local variable. The new frame is then made current, and the Java Virtual Machinepc
is set to the opcode of the first instruction of the method to be invoked. Execution continues with the first instruction of the method.If the method is
native
and the platform-dependent code that implements it has not yet been bound (5.6) into the Java Virtual Machine, that is done. The nargs argument values are popped from the operand stack and are passed as parameters to the code that implements the method. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being passed as a parameter. The parameters are passed and the code is invoked in an implementation-dependent manner. When the platform-dependent code returns, the following take place:If the
native
method issynchronized
, the monitor associated with the resolvedClass
object is updated and possibly exited as if by execution of a monitorexit instruction (6.5.monitorexit) in the current thread.If the
native
method returns a value, the return value of the platform-dependent code is converted in an implementation-dependent way to the return type of thenative
method and pushed onto the operand stack.
- Linking Exceptions
During resolution of the symbolic reference to the method, any of the exceptions pertaining to method resolution (5.4.3.3) can be thrown.
Otherwise, if the resolved method is an instance method, the invokestatic instruction throws an
IncompatibleClassChangeError
.- Run-time Exceptions
Otherwise, if execution of this invokestatic instruction causes initialization of the
referenceddeclaring class or interface, invokestatic may throw anError
as detailed in 5.5.Otherwise, if the resolved method is
native
and the code that implements the method cannot be bound, invokestatic throws anUnsatisfiedLinkError
.- Notes
The nargs argument values are not one-to-one with the first nargs local variables. Argument values of types
long
anddouble
must be stored in two consecutive local variables, thus more than nargs local variables may be required to pass nargs argument values to the invoked method.
invokevirtual
- Operation
Invoke instance method; dispatch based on class
- Format
invokevirtual
indexbyte1
indexbyte2- Forms
invokevirtual = 182 (0xb6)
- Operand Stack
..., objectref, [arg1, [arg2 ...]] →
...
- Description
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1
<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a method (5.1), which gives the name and descriptor (4.3.3) of the method as well as a symbolic reference to the class, interface, or array type in which the method is to be found. The named method is resolved (5.4.3.3).If the resolved method is not signature polymorphic (2.9.3), then the invokevirtual instruction proceeds as follows.
Let C be the class or array type of objectref. A method is selected with respect to C and the resolved method (5.4.6). This is the method to be invoked.
The objectref must be followed on the operand stack by nargs argument values, where the number, type, and order of the values must be consistent with the descriptor of the selected instance method.
If the method to be invoked is
synchronized
, the monitor associated with objectref is entered or reentered as if by execution of a monitorenter instruction (6.5.monitorenter) in the current thread.If the method to be invoked is not
native
, the nargs argument values and objectref are popped from the operand stack. A new frame is created on the Java Virtual Machine stack for the method being invoked. The objectref and the argument values are consecutively made the values of local variables of the new frame, with objectref in local variable 0, arg1 in local variable 1 (or, if arg1 is of typelong
ordouble
, in local variables 1 and 2), and so on. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being stored in a local variable. The new frame is then made current, and the Java Virtual Machinepc
is set to the opcode of the first instruction of the method to be invoked. Execution continues with the first instruction of the method.If the method to be invoked is
native
and the platform-dependent code that implements it has not yet been bound (5.6) into the Java Virtual Machine, that is done. The nargs argument values and objectref are popped from the operand stack and are passed as parameters to the code that implements the method. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being passed as a parameter. The parameters are passed and the code is invoked in an implementation-dependent manner. When the platform-dependent code returns, the following take place:If the
native
method issynchronized
, the monitor associated with objectref is updated and possibly exited as if by execution of a monitorexit instruction (6.5.monitorexit) in the current thread.If the
native
method returns a value, the return value of the platform-dependent code is converted in an implementation-dependent way to the return type of thenative
method and pushed onto the operand stack.
If the resolved method is signature polymorphic (2.9.3), and declared in the
java.lang.invoke.MethodHandle
class, then the invokevirtual instruction proceeds as follows, where D is the descriptor of the method symbolically referenced by the instruction.First, a
reference
to an instance ofjava.lang.invoke.MethodType
is obtained as if by resolution of a symbolic reference to a method type (5.4.3.5) with the same parameter and return types as D.If the named method is
invokeExact
, the instance ofjava.lang.invoke.MethodType
must be semantically equal to the type descriptor of the receiving method handle objectref. The method handle to be invoked is objectref.If the named method is
invoke
, and the instance ofjava.lang.invoke.MethodType
is semantically equal to the type descriptor of the receiving method handle objectref, then the method handle to be invoked is objectref.If the named method is
invoke
, and the instance ofjava.lang.invoke.MethodType
is not semantically equal to the type descriptor of the receiving method handle objectref, then the Java Virtual Machine attempts to adjust the type descriptor of the receiving method handle, as if by invocation of theasType
method ofjava.lang.invoke.MethodHandle
, to obtain an exactly invokable method handle m. The method handle to be invoked is m.
The objectref must be followed on the operand stack by nargs argument values, where the number, type, and order of the values must be consistent with the type descriptor of the method handle to be invoked. (This type descriptor will correspond to the method descriptor appropriate for the kind of the method handle to be invoked, as specified in 5.4.3.5.)
Then, if the method handle to be invoked has bytecode behavior, the Java Virtual Machine invokes the method handle as if by execution of the bytecode behavior associated with the method handle's kind. If the kind is 5 (
REF_invokeVirtual
), 6 (REF_invokeStatic
), 7 (REF_invokeSpecial
), 8 (REF_newInvokeSpecial
), or 9 (REF_invokeInterface
), then a frame will be created and made current in the course of executing the bytecode behavior; however, this frame is not visible, and when the method invoked by the bytecode behavior completes (normally or abruptly), the frame of its invoker is considered to be the frame for the method containing this invokevirtual instruction.Otherwise, if the method handle to be invoked has no bytecode behavior, the Java Virtual Machine invokes it in an implementation-dependent manner.
If the resolved method is signature polymorphic and declared in the
java.lang.invoke.VarHandle
class, then the invokevirtual instruction proceeds as follows, where N and D are the name and descriptor of the method symbolically referenced by the instruction.First, a
reference
to an instance ofjava.lang.invoke.VarHandle.AccessMode
is obtained as if by invocation of thevalueFromMethodName
method ofjava.lang.invoke.VarHandle.AccessMode
with aString
argument denoting N.Second, a
reference
to an instance ofjava.lang.invoke.MethodType
is obtained as if by invocation of theaccessModeType
method ofjava.lang.invoke.VarHandle
on the instance objectref, with the instance ofjava.lang.invoke.VarHandle.AccessMode
as the argument.Third, a
reference
to an instance ofjava.lang.invoke.MethodHandle
is obtained as if by invocation of thevarHandleExactInvoker
method ofjava.lang.invoke.MethodHandles
with the instance ofjava.lang.invoke.VarHandle.AccessMode
as the first argument and the instance ofjava.lang.invoke.MethodType
as the second argument. The resulting instance is called the invoker method handle.Finally, the nargs argument values and objectref are popped from the operand stack, and the invoker method handle is invoked. The invocation occurs as if by execution of an invokevirtual instruction that indicates a run-time constant pool index to a symbolic reference R where:
R is a symbolic reference to a method of a class;
for the symbolic reference to the class in which the method is to be found, R specifies
java.lang.invoke.MethodHandle
;for the name of the method, R specifies
invoke
;for the descriptor of the method, R specifies a return type indicated by the return descriptor of D, and specifies a first parameter type of
java.lang.invoke.VarHandle
followed by the parameter types indicated by the parameter descriptors of D (if any) in order.
and where it is as if the following items were pushed, in order, onto the operand stack:
a
reference
to the instance ofjava.lang.invoke.MethodHandle
(the invoker method handle);objectref;
the nargs argument values, where the number, type, and order of the values must be consistent with the type descriptor of the invoker method handle.
- Linking Exceptions
During resolution of the symbolic reference to the method, any of the exceptions pertaining to method resolution (5.4.3.3) can be thrown.
Otherwise, if the resolved method is a
class (static
)method, the invokevirtual instruction throws anIncompatibleClassChangeError
.Otherwise, if the resolved method is signature polymorphic and declared in the
java.lang.invoke.MethodHandle
class, then during resolution of the method type derived from the descriptor in the symbolic reference to the method, any of the exceptions pertaining to method type resolution (5.4.3.5) can be thrown.Otherwise, if the resolved method is signature polymorphic and declared in the
java.lang.invoke.VarHandle
class, then any linking exception that may arise from invocation of the invoker method handle can be thrown. No linking exceptions are thrown from invocation of thevalueFromMethodName
,accessModeType
, andvarHandleExactInvoker
methods.- Run-time Exceptions
Otherwise, if objectref is
null
, the invokevirtual instruction throws aNullPointerException
.Otherwise, if the resolved method is not signature polymorphic:
If the selected method is
abstract
, invokevirtual throws anAbstractMethodError
.Otherwise, if the selected method is
native
and the code that implements the method cannot be bound, invokevirtual throws anUnsatisfiedLinkError
.Otherwise, if no method is selected, and there are multiple maximally-specific superinterface methods of C that match the resolved method's name and descriptor and are not
abstract
, invokevirtual throws anIncompatibleClassChangeError
.Otherwise, if no method is selected, and there are no maximally-specific superinterface methods of C that match the resolved method's name and descriptor and are not
abstract
, invokevirtual throws anAbstractMethodError
.
Otherwise, if the resolved method is signature polymorphic and declared in the
java.lang.invoke.MethodHandle
class, then:If the method name is
invokeExact
, and the obtained instance ofjava.lang.invoke.MethodType
is not semantically equal to the type descriptor of the receiving method handle objectref, the invokevirtual instruction throws ajava.lang.invoke.WrongMethodTypeException
.If the method name is
invoke
, and the obtained instance ofjava.lang.invoke.MethodType
is not a valid argument to theasType
method ofjava.lang.invoke.MethodHandle
invoked on the receiving method handle objectref, the invokevirtual instruction throws ajava.lang.invoke.WrongMethodTypeException
.
Otherwise, if the resolved method is signature polymorphic and declared in the
java.lang.invoke.VarHandle
class, then any run-time exception that may arise from invocation of the invoker method handle can be thrown. No run-time exceptions are thrown from invocation of thevalueFromMethodName
,accessModeType
, andvarHandleExactInvoker
methods, exceptNullPointerException
if objectref isnull
.- Notes
The nargs argument values and objectref are not one-to-one with the first nargs+1 local variables. Argument values of types
long
anddouble
must be stored in two consecutive local variables, thus more than nargs local variables may be required to pass nargs argument values to the invoked method.It is possible that the symbolic reference of an invokevirtual instruction resolves to an interface method. In this case, it is possible that there is no overriding method in the class hierarchy, but that a non-
abstract
interface method matches the resolved method's descriptor. The selection logic matches such a method, using the same rules as for invokeinterface.
ldc
- Operation
Push item from run-time constant pool
- Format
ldc
index- Forms
ldc = 18 (0x12)
- Operand Stack
... →
..., value
- Description
The index is an unsigned byte that must be a valid index into the run-time constant pool of the current class (2.5.5). The run-time constant pool entry at index must be loadable (5.1), and not any of the following:
A numeric constant of type
long
ordouble
.A symbolic reference to a dynamically-computed constant whose field descriptor is
J
(denotinglong
) orD
(denotingdouble
).
If the run-time constant pool entry is a numeric constant of type
int
orfloat
, then the value of that numeric constant is pushed onto the operand stack as anint
orfloat
, respectively.Otherwise, if the run-time constant pool entry is a string constant, that is, a
reference
to an instance of classString
, then value, areference
to that instance, is pushed onto the operand stack.Otherwise, if the run-time constant pool entry is a symbolic reference to a class,
orinterface, or array type, then thenamed class or interfacesymbolic reference is resolved (5.4.3.1) and value, areference
to theClass
object representing that class,orinterface, or array type, is pushed onto the operand stack.Otherwise, the run-time constant pool entry is a symbolic reference to a method type, a method handle, or a dynamically-computed constant. The symbolic reference is resolved (5.4.3.5, 5.4.3.6) and value, the result of resolution, is pushed onto the operand stack.
- Linking Exceptions
During resolution of a symbolic reference, any of the exceptions pertaining to resolution of that kind of symbolic reference can be thrown.
- Notes
The ldc instruction can only be used to push a value of type
float
taken from the float value set (2.3.2) because a constant of typefloat
in the constant pool (4.4.4) must be taken from the float value set.
ldc_w
- Operation
Push item from run-time constant pool (wide index)
- Format
ldc_w
indexbyte1
indexbyte2- Forms
ldc_w = 19 (0x13)
- Operand Stack
... →
..., value
- Description
The unsigned indexbyte1 and indexbyte2 are assembled into an unsigned 16-bit index into the run-time constant pool of the current class (2.5.5), where the value of the index is calculated as (indexbyte1
<<
8) | indexbyte2. The index must be a valid index into the run-time constant pool of the current class. The run-time constant pool entry at the index must be loadable (5.1), and not any of the following:A numeric constant of type
long
ordouble
.A symbolic reference to a dynamically-computed constant whose field descriptor is
J
(denotinglong
) orD
(denotingdouble
).
If the run-time constant pool entry is a numeric constant of type
int
orfloat
, or a string constant, then value is determined and pushed onto the operand stack according to the rules given for the ldc instruction.Otherwise, the run-time constant pool entry is a symbolic reference to a class, interface, array type, method type, method handle, or dynamically-computed constant. It is resolved and value is determined and pushed onto the operand stack according to the rules given for the ldc instruction.
- Linking Exceptions
During resolution of a symbolic reference, any of the exceptions pertaining to resolution of that kind of symbolic reference can be thrown.
- Notes
The ldc_w instruction is identical to the ldc instruction (6.5.ldc) except for its wider run-time constant pool index.
The ldc_w instruction can only be used to push a value of type
float
taken from the float value set (2.3.2) because a constant of typefloat
in the constant pool (4.4.4) must be taken from the float value set.
multianewarray
- Operation
Create new multidimensional array
- Format
multianewarray
indexbyte1
indexbyte2
dimensions- Forms
multianewarray = 197 (0xc5)
- Operand Stack
..., count1, [count2, ...] →
..., arrayref
- Description
The dimensions operand is an unsigned byte that must be greater than or equal to 1. It represents the number of dimensions of the array to be created. The operand stack must contain dimensions values. Each such value represents the number of components in a dimension of the array to be created, must be of type
int
, and must be non-negative. The count1 is the desired length in the first dimension, count2 in the second, etc.All of the count values are popped off the operand stack. The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1
<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference toa class, array, or interface typean array type. Thenamed class, array, or interface typereferenced array type is resolved (5.4.3.1). The resulting entry must be an arrayclasstype of dimensionality greater than or equal to dimensions.Verification has ensured that the referenced
CONSTANT_Class_info
denotes an array type.A new multidimensional array of the array type is allocated from the garbage-collected heap. If any count value is zero, no subsequent dimensions are allocated. The components of the array in the first dimension are initialized to subarrays of the type of the second dimension, and so on. The components of the last allocated dimension of the array are initialized to the default initial value (2.3, 2.4) for the
element type of the array typecomponent type of that dimension. Areference
arrayref to the new array is pushed onto the operand stack.- Linking Exceptions
During resolution of the symbolic reference to the
class, array, or interface typearray type, any of the exceptions documented in 5.4.3.1 can be thrown.Otherwise, if the current class does not have permission to access the element type of the resolved array class, multianewarray throws anIllegalAccessError
.If the element type is inaccessible, resolution will fail.
- Run-time Exception
Otherwise, if any of the dimensions values on the operand stack are less than zero, the multianewarray instruction throws a
NegativeArraySizeException
.- Notes
It may be more efficient to use newarray or anewarray (6.5.newarray, 6.5.anewarray) when creating an array of a single dimension.
The array
classtype referenced via the run-time constant pool may have more dimensions than the dimensions operand of the multianewarray instruction. In that case, only the first dimensions of the dimensions of the array are created.
new
- Operation
Create new object
- Format
new
indexbyte1
indexbyte2- Forms
new = 187 (0xbb)
- Operand Stack
... →
..., objectref
- Description
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1
<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a class or interfacetype. The named class or interfacetypeis resolved (5.4.3.1) and should result in a non-abstract
classtype. Memory for a new instance of that class is allocated from the garbage-collected heap, and the instance variables of the new object are initialized totheirthe default initial values of their types (2.3, 2.4). The objectref, areference
to the instance, is pushed onto the operand stack.On successful resolution of the class, it is initialized if it has not already been initialized (5.5).
- Linking Exceptions
During resolution of the symbolic reference to the class or interface
type, any of the exceptions documented in 5.4.3.1 can be thrown.Otherwise, if the symbolic reference to the class or interface type resolves to an interface or an
abstract
class, new throws anInstantiationError
.- Run-time Exception
Otherwise, if execution of this new instruction causes initialization of the referenced class, new may throw an
Error
as detailed inJLS §15.9.45.5.This is an unnecessary JLS reference, and also appears to be out of date: JLS 15.9.4 doesn't describe class initialization at all.
- Notes
The new instruction does not completely create a new instance; instance creation is not completed until an instance initialization method (2.9.1) has been invoked on the uninitialized instance.
putfield
- Operation
Set field in object
- Format
putfield
indexbyte1
indexbyte2- Forms
putfield = 181 (0xb5)
- Operand Stack
..., objectref, value →
...
- Description
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1
<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a field (5.1), which gives the name and descriptor of the field as well as a symbolic reference to the class, interface, or array type in which The referenced field is resolved (5.4.3.2).The type of a value stored by a putfield instruction must be compatible with the descriptor of the referenced field (4.3.2). If the field descriptor type is
boolean
,byte
,char
,short
, orint
, then the value must be anint
. If the field descriptor type isfloat
,long
, ordouble
, then the value must be afloat
,long
, ordouble
, respectively. If the field descriptor type is a reference type, then the value must be a value ofa type that is assignment compatible (JLS §5.2) withthe field descriptor type. If the field isfinal
, it must be declared in the current class, and the instruction must occur in an instance initialization method of the current class (2.9.1).The value and objectref are popped from the operand stack.
The objectref must be of type
reference
but not an array type.If the value is of type
int
and the field descriptor type isboolean
, then theint
value is narrowed by taking the bitwise AND of value and 1, resulting in value'. Otherwise, the value undergoes value set conversion (2.8.3), resulting in value'.The referenced field in objectref is set to value'.
- Linking Exceptions
During resolution of the symbolic reference to the field, any of the exceptions pertaining to field resolution (5.4.3.2) can be thrown.
Otherwise, if the resolved field is a
static
field, putfield throws anIncompatibleClassChangeError
.Otherwise, if the resolved field is
final
, it must be declared in the current class, and the instruction must occur in an instance initialization method of the current class. Otherwise, anIllegalAccessError
is thrown.- Run-time Exception
Otherwise, if objectref is
null
, the putfield instruction throws aNullPointerException
.
putstatic
- Operation
Set static field in class
- Format
putstatic
indexbyte1
indexbyte2- Forms
putstatic = 179 (0xb3)
- Operand Stack
..., value →
...
- Description
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1
<<
8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a field (5.1), which gives the name and descriptor of the field as well as a symbolic reference to the class,orinterface, or array type in which the field is to be found. The referenced field is resolved (5.4.3.2).On successful resolution of the field, the class or interface that declared the resolved field is initialized if that class or interface has not already been initialized (5.5).
The type of a value stored by a putstatic instruction must be compatible with the descriptor of the referenced field (4.3.2). If the field descriptor type is
boolean
,byte
,char
,short
, orint
, then the value must be anint
. If the field descriptor type isfloat
,long
, ordouble
, then the value must be afloat
,long
, ordouble
, respectively. If the field descriptor type is a reference type, then the value must be a value ofa type that is assignment compatible (JLS §5.2) withthe field descriptor type. If the field isfinal
, it must be declared in the current class or interface, and the instruction must occur in the class or interface initialization method of the current class or interface (2.9.2).The value is popped from the operand stack.
If the value is of type
int
and the field descriptor type isboolean
, then theint
value is narrowed by taking the bitwise AND of value and 1, resulting in value'. Otherwise, the value undergoes value set conversion (2.8.3), resulting in value'.The referenced field in the class or interface is set to value'.
- Linking Exceptions
During resolution of the symbolic reference to the class or interface field, any of the exceptions pertaining to field resolution (5.4.3.2) can be thrown.
Otherwise, if the resolved field is not a
static
(class) field or an interface field, putstatic throws anIncompatibleClassChangeError
.Otherwise, if the resolved field is
final
, it must be declared in the current class or interface, and the instruction must occur in the class or interface initialization method of the current class or interface. Otherwise, anIllegalAccessError
is thrown.- Run-time Exception
Otherwise, if execution of this putstatic instruction causes initialization of the referenced class or interface, putstatic may throw an
Error
as detailed in 5.5.- Notes
A putstatic instruction may be used only to set the value of an interface field on the initialization of that field. Interface fields may be assigned to only once, on execution of an interface variable initialization expression when the interface is initialized (5.5, JLS §9.3.1).