Changes to the Java® Virtual Machine Specification • Version 14-internal+0-adhoc.dlsmith.20190628
This document describes changes to the Java Virtual Machine Specification to support inline classes.
It incorporates additional changes from:
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.
Unresolved items:
Incorporate any changes made in JVMS 13 and update links.
Revise/relax the timing of checks performed in 5.4.2.
Consider terminology other than "nullable"/"null-free" to describe L
and Q
types, and note that in the future some Q
types may be nullable.
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
.
There are three five kinds of reference
types: identity class types, inline class types, array types, and interface types, and the Object
type. Their values are references to dynamically created class instances, arrays, or class instances or arrays that implement interfaces, respectively objects.
Most reference types are nullable, meaning the special null
reference (representing the absence of an object) is a value of the type. Some reference types are null-free, meaning that null
is not a value of the type.
An identity class type names a non-inline, non-interface class defined in a class
file (excluding the special class Object
). Identity class types are nullable.
The objects referenced by values of an identity class type are instances of the class or one of its subclasses. Each instance is dynamically allocated and has a unique identity, which is used to determine whether two references are the same. The instance encapsulates instance fields; the values of instance fields may be changed, but doing so does not change the identity of the object.
An inline class type names an inline class defined in a class
file. For each inline class, there is a nullable and a null-free inline class type; these types share the same set of values, with the exception of null
.
The objects referenced by values of an inline class type are instances of the class. Each instance encapsulates instance fields whose values cannot be changed. Inline class instances do not have a unique identity—two references are the same if they reference instances of the same inline class and the values of the objects' instance fields are the same.
An array type consists of a component type with a single dimension (whose length is not given by the type). The component type of an array type may itself be an array type be boolean
, any numeric type, or any reference type. Array types are nullable.
If, starting from any array type, one considers its component type, and then (if that is also an array type) the component type of that type, and so on, eventually one must reach a component type that is not an array type; this is called the element type of the array type. The element type of an array type is necessarily either a primitive type, or a class type, or an interface type. The component type of an array type may itself be an array type; such a type is a multi-dimensional array type. Every array type has a non-array element type. The element type of a single-dimensional array type is its component type; the element type of a multi-dimensional array type is the element type of its component array type (applying this definition recursively).
The objects referenced by values of an array type are dynamically-allocated arrays. Each array object has a unique identity, a component type, and a fixed-length vector of mutable components. Array types are covariant: if an array type has component type T, any array referenced by a value of the array type has, as its component type, T or a subtype of T.
An interface type names an interface defined in a class
file. Interface types are nullable.
The objects referenced by values of an interface type are instances of a class that implements the interface. These instances may be identity objects or inline objects. In the special case of interface types Cloneable
and java.io.Serializable
, the objects referenced by values of an interface type may also be arrays.
The Object
type names the Object
class. The Object
type is nullable.
References of type Object
may refer to any object: identity class instances, inline class instances, arrays, or instances of the Object
class itself. Instances of the Object
class have identity but no fields, and behave like identity class instances.
A reference
value may also be the special null reference, a reference to no object, which will be denoted here by null
. The null
reference initially has no run-time type, but may be cast to any type. The default value of a reference
type is null
.
The default value of a nullable reference type is null
. The default value of a null-free inline class type is a reference to a class instance whose fields all have the default value for their type.
This specification does not mandate a concrete value encoding null
.
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, defaultvalue, 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
.
This notation for instruction families is used throughout this specification.
Although both class instances and arrays are objects, the Java Virtual Machine creates and manipulates class instances and arrays using distinct sets of instructions:
Create a new class instance: new, withfield.
Create a new array: newarray, anewarray, multianewarray.
Access fields of classes (static
fields, known as class variables) and fields of class instances (non-static
fields, known as instance variables): getstatic, putstatic, getfield, putfield.
Load an array component onto the operand stack: baload, caload, saload, iaload, laload, faload, daload, aaload.
Store a value from the operand stack as an array component: bastore, castore, sastore, iastore, lastore, fastore, dastore, aastore.
Get the length of array: arraylength.
Check properties of class instances or arrays: instanceof, checkcast.
class
File FormatClassFile
StructureA class
file consists of a single ClassFile
structure:
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
The items in the ClassFile
structure are as follows:
The magic
item supplies the magic number identifying the class
file format; it has the value 0xCAFEBABE
.
The values of the minor_version
and major_version
items are the minor and major version numbers of this class
file. Together, a major and a minor version number determine the version of the class
file format. If a class
file has major version number M and minor version number m, we denote the version of its class
file format as M.m.
A Java Virtual Machine implementation which conforms to Java SE N must support exactly the major versions of the class
file format specified for Java SE N in Table 4.1-A. The notation A .. B means major versions A through B inclusive. The column "Corresponding major version" denotes the major version introduced by each Java SE release, that is, the first release that could have accepted a class
file containing that major_version
item. For very early releases, the JDK version is shown instead of the Java SE release.
Table 4.1-A. class
file format major versions
Java SE | Corresponding major version | Supported major versions |
---|---|---|
1.0.2 | 45 | 45 |
1.1 | 45 | 45 |
1.2 | 46 | 45 .. 46 |
1.3 | 47 | 45 .. 47 |
1.4 | 48 | 45 .. 48 |
5.0 | 49 | 45 .. 49 |
6 | 50 | 45 .. 50 |
7 | 51 | 45 .. 51 |
8 | 52 | 45 .. 52 |
9 | 53 | 45 .. 53 |
10 | 54 | 45 .. 54 |
11 | 55 | 45 .. 55 |
12 | 56 | 45 .. 56 |
For a class
file whose major_version
is 56 or above, the minor_version
must be 0 or 65535.
For a class
file whose major_version
is between 45 and 55 inclusive, the minor_version
may be any value.
A historical perspective on versions of the
class
file format is warranted. JDK 1.0.2 supported versions 45.0 through 45.3 inclusive. JDK 1.1 supported versions 45.0 through 45.65535 inclusive. When JDK 1.2 introduced support for major version 46, the only minor version supported under that major version was 0. Later JDKs continued the practice of introducing support for a new major version (47, 48, etc) but supporting only a minor version of 0 under the new major version. Finally, the introduction of preview features in Java SE 12 (see below) motivated a standard role for the minor version of theclass
file format, so JDK 12 supported minor versions of 0 and 65535 under major version 56. Subsequent JDKs introduce support for N.0 and N.65535 where N is the corresponding major version of the implemented Java SE Platform.
The Java SE Platform may define preview features. A Java Virtual Machine implementation which conforms to Java SE N (N ≥ 12) must support all the preview features of Java SE N, and none of the preview features of any other Java SE release. The implementation must by default disable the supported preview features, and must provide a way to enable all of them, and must not provide a way to enable only some of them.
A class
file is said to depend on the preview features of Java SE N (N ≥ 12) if it has a major_version
that corresponds to Java SE N (according to Table 4.1-A) and a minor_version
of 65535.
A Java Virtual Machine implementation which conforms to Java SE N (N ≥ 12) must behave as follows:
A class
file that depends on the preview features of Java SE N may be loaded only when the preview features of Java SE N are enabled.
A class
file that depends on the preview features of another Java SE release must never be loaded.
A class
file that does not depend on the preview features of any Java SE release may be loaded regardless of whether the preview features of Java SE N are enabled.
The value of the constant_pool_count
item is equal to the number of entries in the constant_pool
table plus one. A constant_pool
index is considered valid if it is greater than zero and less than constant_pool_count
, with the exception for constants of type long
and double
noted in 4.4.5.
The constant_pool
is a table of structures (4.4) representing various string constants, class and interface names, field names, and other constants that are referred to within the ClassFile
structure and its substructures. The format of each constant_pool
table entry is indicated by its first "tag" byte.
The constant_pool
table is indexed from 1 to constant_pool_count
- 1.
The value of the access_flags
item is a mask of flags used to denote access permissions to and properties of this class or interface. The interpretation of each flag, when set, is specified in Table 4.1-B.
Table 4.1-B. Class access and property modifiers
Flag Name | Value | Interpretation |
---|---|---|
ACC_PUBLIC |
0x0001 | Declared public ; may be accessed from outside its package. |
ACC_FINAL |
0x0010 | Declared final ; no subclasses allowed. |
ACC_SUPER |
0x0020 | Treat superclass methods specially when invoked by the invokespecial instruction. |
ACC_INLINE |
0x0100 | Is an inline class. |
ACC_INTERFACE |
0x0200 | Is an interface, not a class. |
ACC_ABSTRACT |
0x0400 | Declared abstract ; must not be instantiated. |
ACC_SYNTHETIC |
0x1000 | Declared synthetic; not present in the source code. |
ACC_ANNOTATION |
0x2000 | Declared as an annotation type. |
ACC_ENUM |
0x4000 | Declared as an enum type. |
ACC_MODULE |
0x8000 | Is a module, not a class or interface. |
The ACC_MODULE
flag indicates that this class
file defines a module, not a class or interface. If the ACC_MODULE
flag is set, then special rules apply to the class
file which are given at the end of this section. If the ACC_MODULE
flag is not set, then the rules immediately below the current paragraph apply to the class
file.
An interface is distinguished by the ACC_INTERFACE
flag being set. If the ACC_INTERFACE
flag is not set, this class
file defines a class, not an interface.
If the ACC_INTERFACE
flag is set, the ACC_ABSTRACT
flag must also be set, and the ACC_FINAL
, ACC_SUPER
, ACC_ENUM
, ACC_INLINE
, and ACC_MODULE
flags must not be set.
An inline class is identified with the ACC_INLINE
flag being set.
If the ACC_INLINE
flag is set, the ACC_FINAL
flag must also be set, and the ACC_ABSTRACT
, ACC_SUPER
, ACC_ENUM
, ACC_INTERFACE
, and ACC_MODULE
flags must not be set.
If neither the none of the ACC_MODULE
flag nor the ACC_INTERFACE
flagACC_MODULE
, ACC_INTERFACE
, or ACC_INLINE
flags is set, the ClassFile
structure represents a class an identity class or the class Object
, and any of the other flags in Table 4.1-B may be set except ACC_ANNOTATION
.
If the ACC_FINAL
flag is set, the ACC_ABSTRACT
flag must not be set.
The ACC_SUPER
flag indicates which of two alternative semantics is to be expressed by the invokespecial instruction (6.5.invokespecial) if it appears in this class or interface. Compilers to the instruction set of the Java Virtual Machine should set the ACC_SUPER
flag. In Java SE 8 and above, the Java Virtual Machine considers the ACC_SUPER
flag to be set in every class
file, regardless of the actual value of the flag in the class
file and the version of the class
file.
The
ACC_SUPER
flag exists for backward compatibility with code compiled by older compilers for the Java programming language. Prior to JDK 1.0.2, the compiler generatedaccess_flags
in which the flag now representingACC_SUPER
had no assigned meaning, and Oracle's Java Virtual Machine implementation ignored the flag if it was set.
The ACC_SYNTHETIC
flag indicates that this class or interface was generated by a compiler and does not appear in source code.
An annotation type (JLS §9.6) must have its ACC_ANNOTATION
flag set. If the ACC_ANNOTATION
flag is set, the ACC_INTERFACE
flag must also be set.
The ACC_ENUM
flag indicates that this class or its superclass is declared as an enumerated type (JLS §8.9).
All bits of the access_flags
item not assigned in Table 4.1-B are reserved for future use. They should be set to zero in generated class
files and should be ignored by Java Virtual Machine implementations.
In a class
file whose version number is less than 57.0, the ACC_INLINE
flag should not be set and is treated as if it were not set.
Design discussion: access_flags
provide a convenient way to document that a class is an inline class, but there are other ways we could encode the same information. For example, an attribute could be present, or a particular superclass could be used.
The value of the this_class
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure (4.4.1) representing the class or interface defined by this class
file.
The CONSTANT_Utf8_info
of the CONSTANT_Class_info
structure must be a class or interface name, not a field descriptor.
For a class, the value of the super_class
item either must be zero or must be a valid index into the constant_pool
table. If the value of the super_class
item is nonzero, the constant_pool
entry at that index must be a CONSTANT_Class_info
structure representing the direct superclass of the class defined by this class
file. Neither the direct superclass nor any of its superclasses may have the ACC_FINAL
flag set in the access_flags
item of its ClassFile
structure.
If the value of the super_class
item is zero, then this class
file must represent the class Object
, the only class or interface without a direct superclass.
The CONSTANT_Utf8_info
of the CONSTANT_Class_info
structure, if present, must be a class name, not a field descriptor.
For an interface or an inline class, the value of the super_class
item must always be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure representing the class Object
.
The value of the interfaces_count
item gives the number of direct superinterfaces of this class or interface.
Each value in the interfaces
array must be a valid index into the constant_pool
table. The constant_pool
entry at each value of interfaces[*i*]
, where 0 ≤ i < interfaces_count
, must be a CONSTANT_Class_info
structure representing an interface that is a direct superinterface of this class or interface, in the left-to-right order given in the source for the class or interface.
The CONSTANT_Utf8_info
of each CONSTANT_Class_info
structure must be an interface name, not a field descriptor.
The value of the fields_count
item gives the number of field_info
structures in the fields
table. The field_info
structures represent all fields, both class variables and instance variables, declared by this class or interface.
Each value in the fields
table must be a field_info
structure (4.5) giving a complete description of a field in this class or interface. The fields
table includes only those fields that are declared by this class or interface. It does not include items representing fields that are inherited from superclasses or superinterfaces.
The value of the methods_count
item gives the number of method_info
structures in the methods
table.
Each value in the methods
table must be a method_info
structure (4.6) giving a complete description of a method in this class or interface. If neither of the ACC_NATIVE
and ACC_ABSTRACT
flags are set in the access_flags
item of a method_info
structure, the Java Virtual Machine instructions implementing the method are also supplied.
The method_info
structures represent all methods declared by this class or interface, including instance methods, class methods, instance initialization methods (2.9.1), and any class or interface initialization method (2.9.2). The methods
table does not include items representing methods that are inherited from superclasses or superinterfaces.
The value of the attributes_count
item gives the number of attributes in the attributes
table of this class.
Each value of the attributes
table must be an attribute_info
structure (4.7).
The attributes defined by this specification as appearing in the attributes
table of a ClassFile
structure are listed in Table 4.7-C.
The rules concerning attributes defined to appear in the attributes
table of a ClassFile
structure are given in 4.7.
The rules concerning non-predefined attributes in the attributes
table of a ClassFile
structure are given in 4.7.1.
If the ACC_MODULE
flag is set in the access_flags
item, then no other flag in the access_flags
item may be set, and the following rules apply to the rest of the ClassFile
structure:
major_version
, minor_version
: ≥ 53.0 (i.e., Java SE 9 and above)
this_class
: module-info
super_class
, interfaces_count
, fields_count
, methods_count
: zero
attributes
: One Module
attribute must be present. Except for Module
, ModulePackages
, ModuleMainClass
, InnerClasses
, SourceFile
, SourceDebugExtension
, RuntimeVisibleAnnotations
, and RuntimeInvisibleAnnotations
, none of the pre-defined attributes (4.7) may appear.
A field descriptor represents the type of a field, parameter, value, or local variable.
B
C
D
F
I
J
S
Z
L
ClassName ;
Q
ClassName ;
[
ComponentType
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.
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 ; |
|
Q ClassName ; |
Null-free named inline class type |
S |
short |
Z |
boolean |
[ |
Array of given component type |
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
.
Design discussion: the withfield and defaultvalue instructions may justify new forms of CONSTANT_MethodHandle
, but for now no changes are made to 4.4.8.
CONSTANT_Class_info
StructureThe CONSTANT_Class_info
structure is used to represent a class, an interface, or an array a reference type:
CONSTANT_Class_info {
u1 tag;
u2 name_index;
}
The items of the CONSTANT_Class_info
structure are as follows:
The tag
item has the value CONSTANT_Class
(7).
The value of the name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing either a valid binary class or interface name encoded in internal form (4.2.1) or an ArrayType a ReferenceType descriptor (4.3.2).
In a class
file whose version number is less than 57.0, the name_index
item must not be a field descriptor of the form NullableClassType or NullFreeClassType.
For example, the
name_index
string representing the classString
isjava/lang/String
. Thename_index
string representing the identity class typeString
isLjava/lang/String;
. Thename_index
string representing the interfaceRunnable
isjava/lang/Runnable
. Thename_index
string representing the null-free inline class typeFoo
isQFoo;
. Thename_index
string representing the array typeThread[]
is[Ljava/lang/Thread;
. Thename_index
string representing the array typeint[][]
is[[I
.
Note that it is not supported to represent a primitive type with a
CONSTANT_Class_info
. For example, thename_index
stringD
represents a class or interface namedD
, not the primitive typedouble
.
Design discussion: as a minimum, we need a way to encode null-free types for anewarray
. A constant pool encoding is also convenient for ldc
, checkcast
, and bootstrap arguments. For consistency, instanceof
should probably support null-free types too (although instanceof Foo
and instanceof QFoo;
will always have the same result).
The strategy used here is to overload CONSTANT_Class_info
with null-free class type descriptors. In doing so, there's no particular reason (though we may decide to be more restrictive) that L
types can't be supported, too, as an alternative to bare class names in contexts that work on arbitrary types. The only descriptors that can't be allowed, due to syntactic ambiguity, are those for primitive types—supporting primitive types would require new syntax.
Despite the overloading, many contexts that use CONSTANT_Class_info
only permit class or interface names, not arbitrary types. In these contexts, type descriptors continue to be prohibited. The overhead and risks associated with validating all of these contexts may make it worthwhile to instead introduce a new kind of constant for types.
CONSTANT_Fieldref_info
, CONSTANT_Methodref_info
, and CONSTANT_InterfaceMethodref_info
StructuresFields, methods, and interface methods are represented by similar structures:
CONSTANT_Fieldref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
CONSTANT_Methodref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
CONSTANT_InterfaceMethodref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
The items of these structures are as follows:
The tag
item of a CONSTANT_Fieldref_info
structure has the value CONSTANT_Fieldref
(9).
The tag
item of a CONSTANT_Methodref_info
structure has the value CONSTANT_Methodref
(10).
The tag
item of a CONSTANT_InterfaceMethodref_info
structure has the value CONSTANT_InterfaceMethodref
(11).
The value of the class_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure (4.4.1) representing a class or interface that has the field or method as a member.
The CONSTANT_Utf8_info
of the CONSTANT_Class_info
structure must be a class or interface name, not a field descriptor.
In a CONSTANT_Fieldref_info
structure, the class_index
item may be either a class or an interface.
In a CONSTANT_Methodref_info
structure, the class_index
item must be a class, not an interface.
In a CONSTANT_InterfaceMethodref_info
structure, the class_index
item must be an interface, not a class.
The value of the name_and_type_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_NameAndType_info
structure (4.4.6). This constant_pool
entry indicates the name and descriptor of the field or method.
In a CONSTANT_Fieldref_info
structure, the indicated descriptor must be a field descriptor (4.3.2). Otherwise, the indicated descriptor must be a method descriptor (4.3.3).
In a CONSTANT_Methodref_info
structure or a CONSTANT_InterfaceMethodref
structure, the referenced name must be a valid method name (4.2.2).
CONSTANT_NameAndType_info
StructureThe CONSTANT_NameAndType_info
structure is used to represent a field or method, without indicating which class or interface it belongs to:
CONSTANT_NameAndType_info {
u1 tag;
u2 name_index;
u2 descriptor_index;
}
The items of the CONSTANT_NameAndType_info
structure are as follows:
The tag
item has the value CONSTANT_NameAndType
(12).
The value of the name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing a valid unqualified name (4.2.2).
The value of the descriptor_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing a valid field descriptor or method descriptor (4.3.2, 4.3.3).
In a class
file whose version number is less than 57.0, the field or method descriptor must not make use of any type of the form NullFreeClassType.
CONSTANT_MethodType_info
StructureThe CONSTANT_MethodType_info
structure is used to represent a method type:
CONSTANT_MethodType_info {
u1 tag;
u2 descriptor_index;
}
The items of the CONSTANT_MethodType_info
structure are as follows:
The tag
item has the value CONSTANT_MethodType
(16).
The value of the descriptor_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing a method descriptor (4.3.3).
In a class
file whose version number is less than 57.0, the method descriptor must not make use of any type of the form NullFreeClassType.
Each field is described by a field_info
structure.
No two fields in one class
file may have the same name and descriptor (4.3.2).
The structure has the following format:
field_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
The items of the field_info
structure are as follows:
The value of the access_flags
item is a mask of flags used to denote access permission to and properties of this field. The interpretation of each flag, when set, is specified in Table 4.5-A.
Table 4.5-A. Field access and property flags
Flag Name | Value | Interpretation |
---|---|---|
ACC_PUBLIC |
0x0001 | Declared public ; may be accessed from outside its package. |
ACC_PRIVATE |
0x0002 | Declared private ; accessible only within the defining class and other classes belonging to the same nest (5.4.4). |
ACC_PROTECTED |
0x0004 | Declared protected ; may be accessed within subclasses. |
ACC_STATIC |
0x0008 | Declared static . |
ACC_FINAL |
0x0010 | Declared final ; never directly assigned to after object construction (JLS §17.5). |
ACC_VOLATILE |
0x0040 | Declared volatile ; cannot be cached. |
ACC_TRANSIENT |
0x0080 | Declared transient ; not written or read by a persistent object manager. |
ACC_SYNTHETIC |
0x1000 | Declared synthetic; not present in the source code. |
ACC_ENUM |
0x4000 | Declared as an element of an enum . |
Fields of classes may set any of the flags in Table 4.5-A. However, each field of a class may have at most one of its ACC_PUBLIC
, ACC_PRIVATE
, and ACC_PROTECTED
flags set (JLS §8.3.1), and must not have both its ACC_FINAL
and ACC_VOLATILE
flags set (JLS §8.3.1.4). Each field of an inline class must have at least one of its ACC_STATIC
or ACC_FINAL
flags set.
Fields of interfaces must have their ACC_PUBLIC
, ACC_STATIC
, and ACC_FINAL
flags set; they may have their ACC_SYNTHETIC
flag set and must not have any of the other flags in Table 4.5-A set (JLS §9.3).
The ACC_SYNTHETIC
flag indicates that this field was generated by a compiler and does not appear in source code.
The ACC_ENUM
flag indicates that this field is used to hold an element of an enumerated type.
All bits of the access_flags
item not assigned in Table 4.5-A are reserved for future use. They should be set to zero in generated class
files and should be ignored by Java Virtual Machine implementations.
The value of the name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) which represents a valid unqualified name denoting a field (4.2.2).
The value of the descriptor_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) which represents a valid field descriptor (4.3.2).
In a class
file whose version number is less than 57, the field descriptor must not make use of any type of the form NullFreeClassType.
The value of the attributes_count
item indicates the number of additional attributes of this field.
Each value of the attributes
table must be an attribute_info
structure (4.7).
A field can have any number of optional attributes associated with it.
The attributes defined by this specification as appearing in the attributes
table of a field_info
structure are listed in Table 4.7-C.
The rules concerning attributes defined to appear in the attributes
table of a field_info
structure are given in 4.7.
The rules concerning non-predefined attributes in the attributes
table of a field_info
structure are given in 4.7.1.
Each method, including each instance initialization method (2.9.1) and the class or interface initialization method (2.9.2), is described by a method_info
structure.
No two methods in one class
file may have the same name and descriptor (4.3.3).
The structure has the following format:
method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
The items of the method_info
structure are as follows:
The value of the access_flags
item is a mask of flags used to denote access permission to and properties of this method. The interpretation of each flag, when set, is specified in Table 4.6-A.
Table 4.6-A. Method access and property flags
Flag Name | Value | Interpretation |
---|---|---|
ACC_PUBLIC |
0x0001 | Declared public ; may be accessed from outside its package. |
ACC_PRIVATE |
0x0002 | Declared private ; accessible only within the defining class and other classes belonging to the same nest (5.4.4). |
ACC_PROTECTED |
0x0004 | Declared protected ; may be accessed within subclasses. |
ACC_STATIC |
0x0008 | Declared static . |
ACC_FINAL |
0x0010 | Declared final ; must not be overridden (5.4.5). |
ACC_SYNCHRONIZED |
0x0020 | Declared synchronized ; invocation is wrapped by a monitor use. |
ACC_BRIDGE |
0x0040 | A bridge method, generated by the compiler. |
ACC_VARARGS |
0x0080 | Declared with variable number of arguments. |
ACC_NATIVE |
0x0100 | Declared native ; implemented in a language other than the Java programming language. |
ACC_ABSTRACT |
0x0400 | Declared abstract ; no implementation is provided. |
ACC_STRICT |
0x0800 | Declared strictfp ; floating-point mode is FP-strict. |
ACC_SYNTHETIC |
0x1000 | Declared synthetic; not present in the source code. |
An instance initialization method (that is, a method with name <init>
and return descriptor V
) may have at most one of its ACC_PUBLIC
, ACC_PRIVATE
, and ACC_PROTECTED
flags set, and may also have its ACC_VARARGS
, ACC_STRICT
, and ACC_SYNTHETIC
flags set, but must not have any of the other flags in Table 4.6-A set.
In a class
file whose version number is 57.0 or above, a class or interface initialization method (that is, a method declared with name <clinit>
and descriptor ()V
) must have its ACC_STATIC
flag set, and may also have its ACC_STRICT
and ACC_SYNTHETIC
flags set, but must not have any of the other flags in Table 4.6-A set.
In a class
file whose version number is less than 57.0, a class or interface initialization method may have any of the flags in Table 4.6-A set, in any combination, but all flags except ACC_STATIC
, ACC_STRICT
, and ACC_SYNTHETIC
are treated by the Java Virtual Machine as if they were not set. If the major version number is 51 to 56, inclusive, the ACC_STATIC
flag must be set; if the major version number is 50 or below, the ACC_STATIC
flag is treated by the Java Virtual Machine as if it were set.
Methods of classes other than instance initialization methods and the class initialization method may have any of the flags in Table 4.6-A set. However, each non-initialization method of a class may have at most one of its ACC_PUBLIC
, ACC_PRIVATE
, and ACC_PROTECTED
flags set (JLS §8.4.3).
A method of an inline class that has its ACC_SYNCHRONIZED
flag set must also have its ACC_STATIC
flag set.
Methods of interfaces other than the interface initialization method may have any of the flags in Table 4.6-A set except ACC_PROTECTED
, ACC_FINAL
, ACC_SYNCHRONIZED
, and ACC_NATIVE
(JLS §9.4); exactly one of the ACC_PUBLIC
or ACC_PRIVATE
flags must be set. In a class
file whose version number is less than 52.0, each non-initialization method of an interface must have its ACC_PUBLIC
and ACC_ABSTRACT
flags set.
If a method of a class or interface has its ACC_ABSTRACT
flag set, it must not have any of its ACC_PRIVATE
, ACC_STATIC
, ACC_FINAL
, ACC_SYNCHRONIZED
, ACC_NATIVE
, or ACC_STRICT
flags set.
The ACC_BRIDGE
flag is used to indicate a bridge method generated by a compiler for the Java programming language.
The ACC_VARARGS
flag indicates that this method takes a variable number of arguments at the source code level.
The ACC_SYNTHETIC
flag indicates that this method was generated by a compiler and does not appear in source code, and is not one of the methods named in 4.7.8.
All bits of the access_flags
item not assigned in Table 4.6-A are reserved for future use. They should be set to zero in generated class
files and should be ignored by Java Virtual Machine implementations.
The value of the name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing a valid unqualified method name (4.2.2).
The value of the descriptor_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure representing a valid method descriptor (4.3.3).
If this method is declared in an inline class or an interface, and the name of the method is <init>
, then the descriptor must not denote a void
method.
Instance initialization methods are
not allowed in interfacesonly allowed in identity classes and the classObject
.
In a class
file whose version number is less than 57.0, the method descriptor must not make use of any type of the form NullFreeClassType.
A future edition of this specification may require that the last parameter descriptor of the method descriptor is an array type if the
ACC_VARARGS
flag is set in theaccess_flags
item.
The value of the attributes_count
item indicates the number of additional attributes of this method.
Each value of the attributes
table must be an attribute_info
structure (4.7).
A method can have any number of optional attributes associated with it.
The attributes defined by this specification as appearing in the attributes
table of a method_info
structure are listed in Table 4.7-C.
The rules concerning attributes defined to appear in the attributes
table of a method_info
structure are given in 4.7.
The rules concerning non-predefined attributes in the attributes
table of a method_info
structure are given in 4.7.1.
Code
AttributeThe Code
attribute is a variable-length attribute in the attributes
table of a method_info
structure (4.6). A Code
attribute contains the Java Virtual Machine instructions and auxiliary information for a method, including an instance initialization method and a class or interface initialization method (2.9.1, 2.9.2).
If the method is either native
or abstract
, and is not a class or interface initialization method, then its method_info
structure must not have a Code
attribute in its attributes
table. Otherwise, its method_info
structure must have exactly one Code
attribute in its attributes
table.
The Code
attribute has the following format:
Code_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 max_stack;
u2 max_locals;
u4 code_length;
u1 code[code_length];
u2 exception_table_length;
{ u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type;
} exception_table[exception_table_length];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
The items of the Code_attribute
structure are as follows:
The value of the attribute_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing the string "Code
".
The value of the attribute_length
item indicates the length of the attribute, excluding the initial six bytes.
The value of the max_stack
item gives the maximum depth of the operand stack of this method (2.6.2) at any point during execution of the method.
The value of the max_locals
item gives the number of local variables in the local variable array allocated upon invocation of this method (2.6.1), including the local variables used to pass parameters to the method on its invocation.
The greatest local variable index for a value of type long
or double
is max_locals - 2
. The greatest local variable index for a value of any other type is max_locals - 1
.
The value of the code_length
item gives the number of bytes in the code
array for this method.
The value of code_length
must be greater than zero (as the code
array must not be empty) and less than 65536.
The code
array gives the actual bytes of Java Virtual Machine code that implement the method.
When the code
array is read into memory on a byte-addressable machine, if the first byte of the array is aligned on a 4-byte boundary, the tableswitch and lookupswitch 32-bit offsets will be 4-byte aligned. (Refer to the descriptions of those instructions for more information on the consequences of code
array alignment.)
The detailed constraints on the contents of the code
array are extensive and are given in a separate section (4.9).
The value of the exception_table_length
item gives the number of entries in the exception_table
table.
Each entry in the exception_table
array describes one exception handler in the code
array. The order of the handlers in the exception_table
array is significant (2.10).
Each exception_table
entry contains the following four items:
The values of the two items start_pc
and end_pc
indicate the ranges in the code
array at which the exception handler is active. The value of start_pc
must be a valid index into the code
array of the opcode of an instruction. The value of end_pc
either must be a valid index into the code
array of the opcode of an instruction or must be equal to code_length
, the length of the code
array. The value of start_pc
must be less than the value of end_pc
.
The start_pc
is inclusive and end_pc
is exclusive; that is, the exception handler must be active while the program counter is within the interval [start_pc
, end_pc
).
The fact that
end_pc
is exclusive is a historical mistake in the design of the Java Virtual Machine: if the Java Virtual Machine code for a method is exactly 65535 bytes long and ends with an instruction that is 1 byte long, then that instruction cannot be protected by an exception handler. A compiler writer can work around this bug by limiting the maximum size of the generated Java Virtual Machine code for any method, instance initialization method, or static initializer (the size of any code array) to 65534 bytes.
The value of the handler_pc
item indicates the start of the exception handler. The value of the item must be a valid index into the code
array and must be the index of the opcode of an instruction.
If the value of the catch_type
item is nonzero, it must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure (4.4.1) representing a class of exceptions that this exception handler is designated to catch. The exception handler will be called only if the thrown exception is an instance of the given class or one of its subclasses.
The CONSTANT_Utf8_info
of the CONSTANT_Class_info
structure, if present, must be a class or interface name, not a field descriptor.
The verifier checks that the class is
Throwable
or a subclass ofThrowable
(4.9.2).
If the value of the catch_type
item is zero, this exception handler is called for all exceptions.
This is used to implement
finally
(3.13).
The value of the attributes_count
item indicates the number of attributes of the Code
attribute.
Each value of the attributes
table must be an attribute_info
structure (4.7).
A Code
attribute can have any number of optional attributes associated with it.
The attributes defined by this specification as appearing in the attributes
table of a Code
attribute are listed in Table 4.7-C.
The rules concerning attributes defined to appear in the attributes
table of a Code
attribute are given in 4.7.
The rules concerning non-predefined attributes in the attributes
table of a Code
attribute are given in 4.7.1.
StackMapTable
Attribute...
A verification type specifies the type of either one or two locations, where a location is either a single local variable or a single operand stack entry. A verification type is represented by a discriminated union, verification_type_info
, that consists of a one-byte tag, indicating which item of the union is in use, followed by zero or more bytes, giving more information about the tag.
union verification_type_info {
Top_variable_info;
Integer_variable_info;
Float_variable_info;
Long_variable_info;
Double_variable_info;
Null_variable_info;
UninitializedThis_variable_info;
Object_variable_info;
Uninitialized_variable_info;
}
A verification type that specifies one location in the local variable array or in the operand stack is represented by the following items of the verification_type_info
union:
The Top_variable_info
item indicates that the local variable has the verification type top
.
Top_variable_info {
u1 tag = ITEM_Top; /* 0 */
}
The Integer_variable_info
item indicates that the location has the verification type int
.
Integer_variable_info {
u1 tag = ITEM_Integer; /* 1 */
}
The Float_variable_info
item indicates that the location has the verification type float
.
Float_variable_info {
u1 tag = ITEM_Float; /* 2 */
}
The Null_variable_info
type indicates that the location has the verification type null
.
Null_variable_info {
u1 tag = ITEM_Null; /* 5 */
}
The UninitializedThis_variable_info
item indicates that the location has the verification type uninitializedThis
.
UninitializedThis_variable_info {
u1 tag = ITEM_UninitializedThis; /* 6 */
}
The Object_variable_info
item indicates that the location has the verification type which is the class, interface, or array type represented by the CONSTANT_Class_info
structure (4.4.1) found in the constant_pool
table at the index given by cpool_index
.
A CONSTANT_Class_info
structure that references a class or interface name is interpreted in this context as the nullable type of the referenced class or interface.
Object_variable_info {
u1 tag = ITEM_Object; /* 7 */
u2 cpool_index;
}
The Uninitialized_variable_info
item indicates that the location has the verification type uninitialized(Offset)
. The Offset
item indicates the offset, in the code
array of the Code
attribute that contains this StackMapTable
attribute, of the new instruction (6.5.new) that created the object being stored in the location.
Uninitialized_variable_info {
u1 tag = ITEM_Uninitialized; /* 8 */
u2 offset;
}
A verification type that specifies two locations in the local variable array or in the operand stack is represented by the following items of the verification_type_info
union:
The Long_variable_info
item indicates that the first of two locations has the verification type long
.
Long_variable_info {
u1 tag = ITEM_Long; /* 4 */
}
The Double_variable_info
item indicates that the first of two locations has the verification type double
.
Double_variable_info {
u1 tag = ITEM_Double; /* 3 */
}
The Long_variable_info
and Double_variable_info
items indicate the verification type of the second of two locations as follows:
If the first of the two locations is a local variable, then:
It must not be the local variable with the highest index.
The next higher numbered local variable has the verification type top
.
If the first of the two locations is an operand stack entry, then:
It must not be the topmost location of the operand stack.
The next location closer to the top of the operand stack has the verification type top
.
...
Exceptions
AttributeThe Exceptions
attribute is a variable-length attribute in the attributes
table of a method_info
structure (4.6). The Exceptions
attribute indicates which checked exceptions a method may throw.
There may be at most one Exceptions
attribute in the attributes
table of a method_info
structure.
The Exceptions
attribute has the following format:
Exceptions_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_exceptions;
u2 exception_index_table[number_of_exceptions];
}
The items of the Exceptions_attribute
structure are as follows:
The value of the attribute_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be the CONSTANT_Utf8_info
structure (4.4.7) representing the string "Exceptions
".
The value of the attribute_length
item indicates the length of the attribute, excluding the initial six bytes.
The value of the number_of_exceptions
item indicates the number of entries in the exception_index_table
.
Each value in the exception_index_table
array must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure (4.4.1) representing a class that this method is declared to throw.
The CONSTANT_Utf8_info
of each CONSTANT_Class_info
structure must be a class or interface name, not a field descriptor.
A method should throw an exception only if at least one of the following three criteria is met:
The exception is an instance of
RuntimeException
or one of its subclasses.The exception is an instance of
Error
or one of its subclasses.The exception is an instance of one of the exception classes specified in the
exception_index_table
just described, or one of their subclasses.
These requirements are not enforced in the Java Virtual Machine; they are enforced only at compile time.
InnerClasses
AttributeThe InnerClasses
attribute is a variable-length attribute in the attributes
table of a ClassFile
structure (4.1).
If the constant pool of a class or interface C contains at least one CONSTANT_Class_info
entry (4.4.1) which represents names a class or interface that is not a member of a package, then there must be exactly one InnerClasses
attribute in the attributes
table of the ClassFile
structure for C.
The InnerClasses
attribute has the following format:
InnerClasses_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_classes;
{ u2 inner_class_info_index;
u2 outer_class_info_index;
u2 inner_name_index;
u2 inner_class_access_flags;
} classes[number_of_classes];
}
The items of the InnerClasses_attribute
structure are as follows:
The value of the attribute_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing the string "InnerClasses
".
The value of the attribute_length
item indicates the length of the attribute, excluding the initial six bytes.
The value of the number_of_classes
item indicates the number of entries in the classes
array.
Every CONSTANT_Class_info
entry in the constant_pool
table which represents names a class or interface C that is not a package member must have exactly one corresponding entry in the classes
array.
If a class or interface has members that are classes or interfaces, its
constant_pool
table (and hence itsInnerClasses
attribute) must refer to each such member (JLS §13.1), even if that member is not otherwise mentioned by the class.
In addition, the
constant_pool
table of every nested class and nested interface must refer to its enclosing class, so altogether, every nested class and nested interface will haveInnerClasses
information for each enclosing class and for each of its own nested classes and interfaces.
Each entry in the classes
array contains the following four items:
The value of the inner_class_info_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure representing C.
The CONSTANT_Utf8_info
of the CONSTANT_Class_info
structure must be a class or interface name, not a field descriptor.
If C is not a member of a class or an interface - that is, if C is a top-level class or interface (JLS §7.6) or a local class (JLS §14.3) or an anonymous class (JLS §15.9.5) - then the value of the outer_class_info_index
item must be zero.
Otherwise, the value of the outer_class_info_index
item must be a valid index into the constant_pool
table, and the entry at that index must be a CONSTANT_Class_info
structure representing the class or interface of which C is a member. The value of the outer_class_info_index
item must not equal the the value of the inner_class_info_index
item.
The CONSTANT_Utf8_info
of the CONSTANT_Class_info
structure, if present, must be a class or interface name, not a field descriptor.
If C is anonymous (JLS §15.9.5), the value of the inner_name_index
item must be zero.
Otherwise, the value of the inner_name_index
item must be a valid index into the constant_pool
table, and the entry at that index must be a CONSTANT_Utf8_info
structure that represents the original simple name of C, as given in the source code from which this class
file was compiled.
The value of the inner_class_access_flags
item is a mask of flags used to denote access permissions to and properties of class or interface C as declared in the source code from which this class
file was compiled. It is used by a compiler to recover the original information when source code is not available. The flags are specified in Table 4.7.6-A.
Table 4.7.6-A. Nested class access and property flags
Flag Name | Value | Interpretation |
---|---|---|
ACC_PUBLIC |
0x0001 | Marked or implicitly public in source. |
ACC_PRIVATE |
0x0002 | Marked private in source. |
ACC_PROTECTED |
0x0004 | Marked protected in source. |
ACC_STATIC |
0x0008 | Marked or implicitly static in source. |
ACC_FINAL |
0x0010 | Marked or implicitly final in source. |
ACC_INTERFACE |
0x0200 | Was an interface in source. |
ACC_ABSTRACT |
0x0400 | Marked or implicitly abstract in source. |
ACC_SYNTHETIC |
0x1000 | Declared synthetic; not present in the source code. |
ACC_ANNOTATION |
0x2000 | Declared as an annotation type. |
ACC_ENUM |
0x4000 | Declared as an enum type. |
All bits of the inner_class_access_flags
item not assigned in Table 4.7.6-A are reserved for future use. They should be set to zero in generated class
files and should be ignored by Java Virtual Machine implementations.
If a class
file has a version number that is 51.0 or above, and has an InnerClasses
attribute in its attributes
table, then for all entries in the classes
array of the InnerClasses
attribute, the value of the outer_class_info_index
item must be zero if the value of the inner_name_index
item is zero.
Oracle's Java Virtual Machine implementation does not check the consistency of an
InnerClasses
attribute against aclass
file representing a class or interface referenced by the attribute.
EnclosingMethod
AttributeThe EnclosingMethod
attribute is a fixed-length attribute in the attributes
table of a ClassFile
structure (4.1). A class must have an EnclosingMethod
attribute if and only if it represents a local class or an anonymous class (JLS §14.3, JLS §15.9.5).
There may be at most one EnclosingMethod
attribute in the attributes
table of a ClassFile
structure.
The EnclosingMethod
attribute has the following format:
EnclosingMethod_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 class_index;
u2 method_index;
}
The items of the EnclosingMethod_attribute
structure are as follows:
The value of the attribute_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing the string "EnclosingMethod
".
The value of the attribute_length
item must be four.
The value of the class_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure (4.4.1) representing the innermost class or interface that encloses the declaration of the current class.
The CONSTANT_Utf8_info
of the CONSTANT_Class_info
structure must be a class or interface name, not a field descriptor.
If the current class is not immediately enclosed by a method or constructor, then the value of the method_index
item must be zero.
In particular,
method_index
must be zero if the current class was immediately enclosed in source code by an instance initializer, static initializer, instance variable initializer, or class variable initializer. (The first two concern both local classes and anonymous classes, while the last two concern anonymous classes declared on the right hand side of a field assignment.)
Otherwise, the value of the method_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_NameAndType_info
structure (4.4.6) representing the name and type of a method in the class or interface referenced by the class_index
attribute above.
It is the responsibility of a Java compiler to ensure that the method identified via the
method_index
is indeed the closest lexically enclosing method of the class that contains thisEnclosingMethod
attribute.
RuntimeVisibleAnnotations
Attributeelement_value
structureThe element_value
structure is a discriminated union representing the value of an element-value pair. It has the following format:
element_value {
u1 tag;
union {
u2 const_value_index;
{ u2 type_name_index;
u2 const_name_index;
} enum_const_value;
u2 class_info_index;
annotation annotation_value;
{ u2 num_values;
element_value values[num_values];
} array_value;
} value;
}
The tag
item uses a single ASCII character to indicate the type of the value of the element-value pair. This determines which item of the value
union is in use. [Table 4.7.16.1-A] shows the valid characters for the tag
item, the type indicated by each character, and the item used in the value
union for each character. The table's fourth column is used in the description below of one item of the value
union.
Table 4.7.16.1-A. Interpretation of tag
values as types
tag Item |
Type | value Item |
Constant Type |
---|---|---|---|
B |
byte |
const_value_index |
CONSTANT_Integer |
C |
char |
const_value_index |
CONSTANT_Integer |
D |
double |
const_value_index |
CONSTANT_Double |
F |
float |
const_value_index |
CONSTANT_Float |
I |
int |
const_value_index |
CONSTANT_Integer |
J |
long |
const_value_index |
CONSTANT_Long |
S |
short |
const_value_index |
CONSTANT_Integer |
Z |
boolean |
const_value_index |
CONSTANT_Integer |
s |
String |
const_value_index |
CONSTANT_Utf8 |
e |
Enum type | enum_const_value |
Not applicable |
c |
Class |
class_info_index |
Not applicable |
@ |
Annotation type | annotation_value |
Not applicable |
[ |
Array type | array_value |
Not applicable |
The value
item represents the value of an element-value pair. The item is a union, whose own items are as follows:
The const_value_index
item denotes either a primitive constant value or a String
literal as the value of this element-value pair.
The value of the const_value_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be of a type appropriate to the tag
item, as specified in the fourth column of [Table 4.7.16.1-A].
The enum_const_value
item denotes an enum constant as the value of this element-value pair.
The enum_const_value
item consists of the following two items:
The value of the type_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing a field descriptor (4.3.2). The constant_pool
entry gives the internal form of the binary name of the type of the enum constant represented by this element_value
structure (4.2.1).
The value of the const_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7). The constant_pool
entry gives the simple name of the enum constant represented by this element_value
structure.
The class_info_index
item denotes a class literal as the value of this element-value pair.
The class_info_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_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 this element_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, the corresponding type is C. The return descriptor in the constant_pool
will be a ClassType NullableClassType.
For a class literal representing a null-free inline class type, the return descriptor in the constant_pool
will be a NullFreeClassType.
For a class literal T[].class
, where T[] is an array type, the corresponding type is T[]. The return descriptor in the constant_pool
will 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 the constant_pool
will be a BaseType character.
For a class literal void.class
, the corresponding type is void
. The return descriptor in the constant_pool
will 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;
.
The annotation_value
item denotes a "nested" annotation as the value of this element-value pair.
The value of the annotation_value
item is an annotation
structure ([4.7.16]) that gives the annotation represented by this element_value
structure.
The array_value
item denotes an array as the value of this element-value pair.
The array_value
item consists of the following two items:
The value of the num_values
item gives the number of elements in the array represented by this element_value
structure.
Each value in the values
table gives the corresponding element of the array represented by this element_value
structure.
Module
AttributeThe Module
attribute is a variable-length attribute in the attributes
table of a ClassFile
structure (4.1). The Module
attribute indicates the modules required by a module; the packages exported and opened by a module; and the services used and provided by a module.
There may be at most one Module
attribute in the attributes
table of a ClassFile
structure.
The Module
attribute has the following format:
Module_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 module_name_index;
u2 module_flags;
u2 module_version_index;
u2 requires_count;
{ u2 requires_index;
u2 requires_flags;
u2 requires_version_index;
} requires[requires_count];
u2 exports_count;
{ u2 exports_index;
u2 exports_flags;
u2 exports_to_count;
u2 exports_to_index[exports_to_count];
} exports[exports_count];
u2 opens_count;
{ u2 opens_index;
u2 opens_flags;
u2 opens_to_count;
u2 opens_to_index[opens_to_count];
} opens[opens_count];
u2 uses_count;
u2 uses_index[uses_count];
u2 provides_count;
{ u2 provides_index;
u2 provides_with_count;
u2 provides_with_index[provides_with_count];
} provides[provides_count];
}
The items of the Module_attribute
structure are as follows:
The value of the attribute_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing the string "Module
".
The value of the attribute_length
item indicates the length of the attribute, excluding the initial six bytes.
The value of the module_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Module_info
structure (4.4.11) denoting the current module.
The value of the module_flags
item is as follows:
ACC_OPEN
)Indicates that this module is open.
ACC_SYNTHETIC
)Indicates that this module was not explicitly or implicitly declared.
ACC_MANDATED
)Indicates that this module was implicitly declared.
The value of the module_version_index
item must be either zero or a valid index into the constant_pool
table. If the value of the item is zero, then no version information about the current module is present. If the value of the item is nonzero, then the constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure representing the version of the current module.
The value of the requires_count
item indicates the number of entries in the requires
table.
If the current module is java.base
, then requires_count
must be zero.
If the current module is not java.base
, then requires_count
must be at least one.
Each entry in the requires
table specifies a dependence of the current module. The items in each entry are as follows:
The value of the requires_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Module_info
structure denoting a module on which the current module depends.
At most one entry in the requires
table may specify a module of a given name with its requires_index
item.
The value of the requires_flags
item is as follows:
ACC_TRANSITIVE
)Indicates that any module which depends on the current module, implicitly declares a dependence on the module indicated by this entry.
ACC_STATIC_PHASE
)Indicates that this dependence is mandatory in the static phase, i.e., at compile time, but is optional in the dynamic phase, i.e., at run time.
ACC_SYNTHETIC
)Indicates that this dependence was not explicitly or implicitly declared in the source of the module declaration.
ACC_MANDATED
)Indicates that this dependence was implicitly declared in the source of the module declaration.
If the current module is not java.base
, and the class
file version number is 54.0 or above, then neither ACC_TRANSITIVE
nor ACC_STATIC_PHASE
may be set in requires_flags
.
The value of the requires_version_index
item must be either zero or a valid index into the constant_pool
table. If the value of the item is zero, then no version information about the dependence is present. If the value of the item is nonzero, then the constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure representing the version of the module specified by requires_index
.
Unless the current module is java.base
, exactly one entry in the requires
table must have both a requires_index
item which indicates java.base
and a requires_flags
item which has the ACC_SYNTHETIC
flag not set.
The value of the exports_count
item indicates the number of entries in the exports
table.
Each entry in the exports
table specifies a package exported by the current module, such that public
and protected
types in the package, and their public
and protected
members, may be accessed from outside the current module, possibly from a limited set of "friend" modules.
The items in each entry are as follows:
The value of the exports_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Package_info
structure (4.4.12) representing a package exported by the current module.
At most one entry in the exports
table may specify a package of a given name with its exports_index
item.
The value of the exports_flags
item is as follows:
ACC_SYNTHETIC
)Indicates that this export was not explicitly or implicitly declared in the source of the module declaration.
ACC_MANDATED
)Indicates that this export was implicitly declared in the source of the module declaration.
The value of the exports_to_count
indicates the number of entries in the exports_to_index
table.
If exports_to_count
is zero, then this package is exported by the current module in an unqualified fashion; code in any other module may access the types and members in the package.
If exports_to_count
is nonzero, then this package is exported by the current module in a qualified fashion; only code in the modules listed in the exports_to_index
table may access the types and members in the package.
The value of each entry in the exports_to_index
table must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Module_info
structure denoting a module whose code can access the types and members in this exported package.
For each entry in the exports
table, at most one entry in its exports_to_index
table may specify a module of a given name.
The value of the opens_count
item indicates the number of entries in the opens
table.
opens_count
must be zero if the current module is open.
Each entry in the opens
table specifies a package opened by the current module, such that all types in the package, and all their members, may be accessed from outside the current module via the reflection libraries of the Java SE Platform, possibly from a limited set of "friend" modules.
The items in each entry are as follows:
The value of the opens_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Package_info
structure representing a package opened by the current module.
At most one entry in the opens
table may specify a package of a given name with its opens_index
item.
The value of the opens_flags
item is as follows:
ACC_SYNTHETIC
)Indicates that this opening was not explicitly or implicitly declared in the source of the module declaration.
ACC_MANDATED
)Indicates that this opening was implicitly declared in the source of the module declaration.
The value of the opens_to_count
indicates the number of entries in the opens_to_index
table.
If opens_to_count
is zero, then this package is opened by the current module in an unqualified fashion; code in any other module may reflectively access the types and members in the package.
If opens_to_count
is nonzero, then this package is opened by the current module in a qualified fashion; only code in the modules listed in the exports_to_index
table may reflectively access the types and members in the package.
The value of each entry in the opens_to_index
table must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Module_info
structure denoting a module whose code can access the types and members in this opened package.
For each entry in the opens
table, at most one entry in its opens_to_index
table may specify a module of a given name.
The value of the uses_count
item indicates the number of entries in the uses_index
table.
The value of each entry in the uses_index
table must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure (4.4.1) representing a service interface which the current module may discover via java.util.ServiceLoader
.
The CONSTANT_Utf8_info
of each CONSTANT_Class_info
structure must be a class or interface name, not a field descriptor.
At most one entry in the uses_index
table may specify a service interface of a given name.
The value of the provides_count
item indicates the number of entries in the provides
table.
Each entry in the provides
table represents a service implementation for a given service interface.
The items in each entry are as follows:
The value of the provides_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure representing a service interface for which the current module provides a service implementation.
The CONSTANT_Utf8_info
of the CONSTANT_Class_info
structure must be a class or interface name, not a field descriptor.
At most one entry in the provides
table may specify a service interface of a given name with its provides_index
item.
The value of the provides_with_count
indicates the number of entries in the provides_with_index
table.
provides_with_count
must be nonzero.
The value of each entry in the provides_with_index
table must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure representing a service implementation for the service interface specified by provides_index
.
The CONSTANT_Utf8_info
of each CONSTANT_Class_info
structure must be a class or interface name, not a field descriptor.
For each entry in the provides
table, at most one entry in its provides_with_index
table may specify a service implementation of a given name.
ModuleMainClass
AttributeThe ModuleMainClass
attribute is a fixed-length attribute in the attributes
table of a ClassFile
structure (4.1. The ModuleMainClass
attribute indicates the main class of a module.
There may be at most one ModuleMainClass
attribute in the attributes
table of a ClassFile
structure.
The ModuleMainClass
attribute has the following format:
ModuleMainClass_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 main_class_index;
}
The items of the ModuleMainClass_attribute
structure are as follows:
The value of the attribute_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing the string "ModuleMainClass
".
The value of the attribute_length
item must be two.
The value of the main_class_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure (4.4.1) representing the main class of the current module.
The CONSTANT_Utf8_info
of the CONSTANT_Class_info
structure must be a class or interface name, not a field descriptor.
NestHost
AttributeThe NestHost
attribute is a fixed-length attribute in the attributes
table of a ClassFile
structure. The NestHost
attribute records the nest host of the nest to which the current class or interface claims to belong (5.4.4).
There may be at most one NestHost
attribute in the attributes
table of a ClassFile
structure.
The NestHost
attribute has the following format:
NestHost_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 host_class_index;
}
The items of the NestHost_attribute
structure are as follows:
The value of the attribute_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing the string "NestHost
".
The value of the attribute_length
item must be two.
The value of the host_class_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure (4.4.1) representing a class or interface which is the nest host for the current class or interface.
The CONSTANT_Utf8_info
of the CONSTANT_Class_info
structure must be a class or interface name, not a field descriptor.
If the nest host cannot be loaded, or is not in the same run-time package as the current class or interface, or does not authorize nest membership for the current class or interface, then an error may occur during access control (5.4.4).
NestMembers
AttributeThe NestMembers
attribute is a variable-length attribute in the attributes
table of a ClassFile
structure (4.1). The NestMembers
attribute records the classes and interfaces that are authorized to claim membership in the nest hosted by the current class or interface (5.4.4).
There may be at most one NestMembers
attribute in the attributes
table of a ClassFile
structure.
The attributes
table of a ClassFile
structure must not contain both a NestMembers
attribute and a NestHost
attribute.
This rule prevents a nest host from claiming membership in a different nest. It is implicitly a member of the nest that it hosts.
The NestMembers
attribute has the following format:
NestMembers_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_classes;
u2 classes[number_of_classes];
}
The items of the NestMembers_attribute
structure are as follows:
The value of the attribute_name_index
item must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Utf8_info
structure (4.4.7) representing the string "NestMembers
".
The value of the attribute_length
item indicates the length of the attribute, excluding the initial six bytes.
The value of the number_of_classes
item indicates the number of entries in the classes
array.
Each value in the classes
array must be a valid index into the constant_pool
table. The constant_pool
entry at that index must be a CONSTANT_Class_info
structure (4.4.1) representing a class or interface which is a member of the nest hosted by the current class or interface.
The CONSTANT_Utf8_info
of each CONSTANT_Class_info
structure must be a class or interface name, not a field descriptor.
The
classes
array is consulted by access control (5.4.4). It should consist of references to other classes and interfaces that are in the same run-time package and haveNestHost
attributes which reference the current class or interface. Array items that do not meet these criteria are ignored by access control.
The static constraints on a class
file are those defining the well-formedness of the file. These constraints have been given in the previous sections, except for static constraints on the code in the class
file. The static constraints on the code in a class
file specify how Java Virtual Machine instructions must be laid out in the code
array and what the operands of individual instructions must be.
The static constraints on the instructions in the code
array are as follows:
Only instances of the instructions documented in 6.5 may appear in the code
array. Instances of instructions using the reserved opcodes (6.2) or any opcodes not documented in this specification must not appear in the code
array.
If the class
file version number is 51.0 or above, then neither the jsr opcode or nor the jsr_w opcode may appear in the code
array.
If the class
file version number is less than 57, then neither the defaultvalue opcode nor the withfield opecode may appear in the code
array.
The opcode of the first instruction in the code
array begins at index 0
.
For each instruction in the code
array except the last, the index of the opcode of the next instruction equals the index of the opcode of the current instruction plus the length of that instruction, including all its operands.
The wide instruction is treated like any other instruction for these purposes; the opcode specifying the operation that a wide instruction is to modify is treated as one of the operands of that wide instruction. That opcode must never be directly reachable by the computation.
The last byte of the last instruction in the code
array must be the byte at index code_length - 1
.
The static constraints on the operands of instructions in the code
array are as follows:
The target of each jump and branch instruction (jsr, jsr_w, goto, goto_w, ifeq, ifne, ifle, iflt, ifge, ifgt, ifnull, ifnonnull, if_icmpeq, if_icmpne, if_icmple, if_icmplt, if_icmpge, if_icmpgt, if_acmpeq, if_acmpne) must be the opcode of an instruction within this method.
The target of a jump or branch instruction must never be the opcode used to specify the operation to be modified by a wide instruction; a jump or branch target may be the wide instruction itself.
Each target, including the default, of each tableswitch instruction must be the opcode of an instruction within this method.
Each tableswitch instruction must have a number of entries in its jump table that is consistent with the value of its low and high jump table operands, and its low value must be less than or equal to its high value.
No target of a tableswitch instruction may be the opcode used to specify the operation to be modified by a wide instruction; a tableswitch target may be a wide instruction itself.
Each target, including the default, of each lookupswitch instruction must be the opcode of an instruction within this method.
Each lookupswitch instruction must have a number of match-offset pairs that is consistent with the value of its npairs operand. The match-offset pairs must be sorted in increasing numerical order by signed match value.
No target of a lookupswitch instruction may be the opcode used to specify the operation to be modified by a wide instruction; a lookupswitch target may be a wide instruction itself.
The operands of each ldc instruction and each ldc_w instruction must represent a valid index into the constant_pool
table. The constant pool entry referenced by that index must be loadable (4.4), and not any of the following:
An entry of kind CONSTANT_Long
or CONSTANT_Double
.
An entry of kind CONSTANT_Dynamic
that references a CONSTANT_NameAndType_info
structure which indicates a descriptor of J
(denoting long
) or D
(denoting double
).
The operands of each ldc2_w instruction must represent a valid index into the constant_pool
table. The constant pool entry referenced by that index must be loadable, and in particular one of the following:
An entry of kind CONSTANT_Long
or CONSTANT_Double
.
An entry of kind CONSTANT_Dynamic
that references a CONSTANT_NameAndType_info
structure which indicates a descriptor of J
(denoting long
) or D
(denoting double
).
The subsequent constant pool index must also be a valid index into the constant pool, and the constant pool entry at that index must not be used.
The operands of each getfield, putfield, withfield, getstatic, and putstatic instruction must represent a valid index into the constant_pool
table. The constant pool entry referenced by that index must be of kind CONSTANT_Fieldref
.
The indexbyte operands of each invokevirtual, invokeinterface, invokespecial, and invokestatic instruction must represent a valid index into the constant_pool
table. The constant pool entry referenced by that index must be of kind CONSTANT_Methodref
or CONSTANT_InterfaceMethodref
.
An invokevirtual instruction must reference a constant pool entry of kind CONSTANT_Methodref
.
An invokeinterface instruction must reference a constant pool entry of kind CONSTANT_InterfaceMethodref
.
In a class file whose version number is less than 52.0, an invokespecial or an invokestatic instruction must reference a constant pool entry of kind CONSTANT_Methodref
.
The CONSTANT_Methodref
or CONSTANT_InterfaceMethodref
referenced by an invokevirtual, invokeinterface, invokespecial, or invokestatic instruction must not have name <clinit>
with descriptor ()V
.
The CONSTANT_Methodref
or CONSTANT_InterfaceMethodref
referenced by an invokevirtual, invokeinterface, or invokestatic instruction must not have name <init>
with return descriptor V
.
The value of the count operand of each invokeinterface instruction must reflect the number of local variables necessary to store the arguments to be passed to the interface method, as implied by the descriptor of the CONSTANT_NameAndType_info
structure referenced by the CONSTANT_InterfaceMethodref
constant pool entry.
The fourth operand byte of each invokeinterface instruction must have the value zero.
The indexbyte operands of each invokedynamic instruction must represent a valid index into the constant_pool
table. The constant pool entry referenced by that index must be of kind CONSTANT_InvokeDynamic
.
The third and fourth operand bytes of each invokedynamic instruction must have the value zero.
The operands of each instanceof, checkcast, defaultvalue, new, and anewarray instruction, and the indexbyte operands of each multianewarray instruction, must represent a valid index into the constant_pool
table. The constant pool entry referenced by that index must be of kind CONSTANT_Class
.
Every defaultvalue instruction must reference a constant pool entry of kind CONSTANT_Class
that represents a null-free class type.
No new instruction may reference a constant pool entry of kind Every new instruction must reference a constant pool entry of kind CONSTANT_Class
that represents an array type (4.3.2). The new instruction cannot be used to create an array.CONSTANT_Class
that represents a class or interface. That is, the CONSTANT_Utf8_info
of the CONSTANT_Class_info
structure must be a class or interface name, not a field descriptor.
No anewarray instruction may be used to create an array of more than 255 dimensions.
Every multianewarray instruction must reference a constant pool entry of kind CONSTANT_Class
that represents an array type.
A multianewarray instruction must be used only to create an array of a type that has at least as many dimensions as the value of its dimensions operand. That is, while a multianewarray instruction is not required to create all of the dimensions of the array type referenced by its indexbyte operands, it must not attempt to create more dimensions than are in the array type.
The dimensions operand of each multianewarray instruction must not be zero.
The atype operand of each newarray instruction must take one of the values T_BOOLEAN
(4), T_CHAR
(5), T_FLOAT
(6), T_DOUBLE
(7), T_BYTE
(8), T_SHORT
(9), T_INT
(10), or T_LONG
(11).
The index operand of each iload, fload, aload, istore, fstore, astore, iinc, and ret instruction must be a non-negative integer no greater than max_locals - 1
.
The implicit index of each iload_<n>, fload_<n>, aload_<n>, istore_<n>, fstore_<n>, and astore_<n> instruction must be no greater than max_locals - 1
.
The index operand of each lload, dload, lstore, and dstore instruction must be no greater than max_locals - 2
.
The implicit index of each lload_<n>, dload_<n>, lstore_<n>, and dstore_<n> instruction must be no greater than max_locals - 2
.
The indexbyte operands of each wide instruction modifying an iload, fload, aload, istore, fstore, astore, iinc, or ret instruction must represent a non-negative integer no greater than max_locals - 1
.
The indexbyte operands of each wide instruction modifying an lload, dload, lstore, or dstore instruction must represent a non-negative integer no greater than max_locals - 2
.
The structural constraints on the code
array specify constraints on relationships between Java Virtual Machine instructions. The structural constraints are as follows:
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.
As noted in 2.3.4 and 2.11.1, the Java Virtual Machine implicitly converts values of types
boolean
,byte
,short
, andchar
to typeint
, allowing instructions expecting values of typeint
to operate on them.)
If an instruction can be executed along several different execution paths, the operand stack must have the same depth (2.6.2) prior to the execution of the instruction, regardless of the path taken.
At no point during execution can the operand stack grow to a depth greater than that implied by the max_stack
item.
At no point during execution can more values be popped from the operand stack than it contains.
At no point during execution can the order of the local variable pair holding a value of type long
or double
be reversed or the pair split up. At no point can the local variables of such a pair be operated on individually.
No local variable (or local variable pair, in the case of a value of type long
or double
) can be accessed before it is assigned a value.
Each invokespecial instruction must name one of the following:
an instance initialization method (2.9.1) (that is, an <init>
method with return descriptor V
)
a method in the current class or interface
a method in a superclass of the current class
a method in a direct superinterface of the current class or interface
a method in Object
If an invokespecial instruction names an instance initialization method, then the target reference on the operand stack must be an uninitialized class instance. An instance initialization method must never be invoked on an initialized class instance. In addition:
If the target reference on the operand stack is an uninitialized class instance for the current class, then invokespecial must name an instance initialization method from the current class or its direct superclass.
If an invokespecial instruction names an instance initialization method and the target reference on the operand stack is a class instance created by an earlier new instruction, then invokespecial must name an instance initialization method from the class of that class instance.
If an invokespecial instruction names a method which is not an instance initialization method, then the target reference on the operand stack must be a class instance whose type is assignment compatible with the current class (JLS §5.2).
The general rule for invokespecial is that the class or interface named by invokespecial must be be "above" the caller class or interface, while the receiver object targeted by invokespecial must be "at" or "below" the caller class or interface. The latter clause is especially important: a class or interface can only perform invokespecial on its own objects. See 4.10.1.9.invokespecial for an explanation of how the latter clause is implemented in Prolog.
Each instance initialization method, except for the instance initialization method derived from the constructor of class Object
, must call either another instance initialization method of this
or an instance initialization method of its direct superclass super
before its instance members are accessed.
However, instance fields of this
that are declared in the current class may be assigned by putfield before calling any instance initialization method.
When any instance method is invoked or when any instance variable is accessed, the class instance that contains the instance method or instance variable must already be initialized.
<init>
method, the handler must throw an exception or loop forever; and
<init>
method, the uninitialized class instance must remain uninitialized.There must never be an uninitialized class instance on the operand stack or in a local variable when a jsr or jsr_w instruction is executed.
When an invokevirtual or invokespecial instruction references a method of a class, the type of every class instance that is the target of the instruction (that is, the type of the target reference on the operand stack) must be the a class type of the referenced class or one of its subclasses.
The types of the arguments to each method invocation must be subtypes of the types given by the method descriptor (4.10.1.2, 4.3.3), where descriptor types boolean
, byte
, char
, and short
are interpreted as type int
.
Each return instruction must match its method's return type:
If the method returns a boolean
, byte
, char
, short
, or int
, only the ireturn instruction may be used.
If the method returns a float
, long
, or double
, only an freturn, lreturn, or dreturn instruction, respectively, may be used.
If the method returns a reference
type, only an areturn instruction may be used, and the type of the returned value must be a subtype of the return descriptor of the method (4.3.3).
All methods declared to return void
must use only the return instruction.
The type of every class instance accessed by a getfield, putfield, or withfield instruction or modified by a putfield instruction (that is, the type of the target reference on the operand stack) must be the a class type of the class specified in the instruction or one of its subclasses.
The type of every value stored by a putfield, withfield, or putstatic instruction must be compatible with the descriptor of the field (4.3.2) of the class instance or class being stored into:
If the descriptor type is boolean
, byte
, char
, short
, or int
, then the value must be an int
.
If the descriptor type is float
, long
, or double
, then the value must be a float
, long
, or double
, respectively.
If the descriptor type is a reference
type, then the value must be of a type that is a subtype of the descriptor type.
The type of every value stored into an array by an aastore instruction must be a reference
type.
The component type of the array being stored into by the aastore instruction must also be a reference
type.
Each athrow instruction must throw only values that are instances of class Throwable
or of subclasses of Throwable
.
Each class mentioned in a catch_type
item of the exception_table
array of the method's Code_attribute
structure must be Throwable
or a subclass of Throwable
.
If getfield or putfield is used to access a protected
field declared in a superclass that is a member of a different run-time package than the current class, then the type of the class instance being accessed (that is, the type of the target reference on the operand stack) must be the a class type of the current class or one of its subclasses.
In principle, this rule should apply to withfield as well. But since the referenced class of withfield must be an inline class, and the superclass of an inline class must be Object, there are no possible field references to which it would apply.
If invokevirtual or invokespecial is used to access a protected
method declared in a superclass that is a member of a different run-time package than the current class, then the type of the class instance being accessed (that is, the type of the target reference on the operand stack) must be the a class type of the current class or one of its subclasses.
Execution never falls off the bottom of the code
array.
No return address (a value of type returnAddress
) may be loaded from a local variable.
The instruction following each jsr or jsr_w instruction may be returned to only by a single ret instruction.
No jsr or jsr_w instruction that is returned to may be used to recursively call a subroutine if that subroutine is already present in the subroutine call chain. (Subroutines can be nested when using try
-finally
constructs from within a finally
clause.)
Each instance of type returnAddress
can be returned to at most once.
If a ret instruction returns to a point in the subroutine call chain above the ret instruction corresponding to a given instance of type returnAddress
, then that instance can never be used as a return address.
class
FilesThe type checker enforces a type system based upon a hierarchy of verification types, illustrated below.
``` Verification type hierarchy:
top
____________/\____________
/ \
/ \
oneWord twoWord
/ | \ / \
/ | \ / \
int float reference long double
/ \
/ \_____________
/ \
/ \
uninitialized +------------------+
/ \ | reference type |
/ \ | hierarchy |
uninitializedThis uninitialized(Offset) +------------------+
uninitialized +-------------------+
/ \ | reference types |
/ \ | and null |
uninitializedThis uninitialized(Offset) +-------------------+
The type null
is no longer a subtype of all reference types, and identifying exactly which reference types it is related to is beyond the scope of this diagram.
Most verification types have a direct correspondence with the primitive and reference types described in 2.2 and represented by field descriptors in Table 4.3-A:
The primitive types double
, float
, int
, and long
(field descriptors D
, F
, I
, J
) each correspond to the verification type of the same name.
The primitive types byte
, char
, short
, and boolean
(field descriptors B
, C
, S
, Z
) all correspond to the verification type int
.
Class Nullable class and interface types (field descriptors beginning L
), including the Object
type, correspond to verification types that use the functor class
. The verification type class(*N*, *L*)
represents the nullable type of the class or interface whose binary name is *N*
as loaded by the loader *L*
. Note that *L*
is an initiating loader (5.3) of the class represented by class(*N*, *L*)
and may, or may not, be the class's defining loader.
For example, the
class typeObject
type would be represented asclass('java/lang/Object', L)
, where the defining loader of class'java/lang/Object'
, as loaded byL
, is the bootstrap loader.
Null-free inline class types (field descriptors beginning Q
) correspond to verification types that use the functor nullfree
. The verification type nullfree(*N*, *L*)
represents the null-free type of the inline class whose binary name is *N*
as loaded by the loader *L*
.
For example, the null-free type of an inline class
Val
would be represented asnullfree('Val', L)
, for an appropriateL
.
Array types (field descriptors beginning [
) correspond to verification types that use the functor arrayOf
. Note that the primitive types byte
, char
, short
, and boolean
do not correspond to verification types, but an array type whose element type is byte
, char
, short
, or boolean
does correspond to a verification type; such verification types support the baload, bastore, caload, castore, saload, sastore, and newarray instructions.
The verification type arrayOf(*T*)
represents the array type whose component type is the verification type *T*
.
The verification type arrayOf(byte)
represents the array type whose component type is byte
.
The verification type arrayOf(char)
represents the array type whose component type is char
.
The verification type arrayOf(short)
represents the array type whose component type is short
.
The verification type arrayOf(boolean)
represents the array type whose component type is boolean
.
For example, the array types
int[]
andObject[]
would be represented by the verification typesarrayOf(int)
andarrayOf(class('java/lang/Object', BL))
respectively. The array typesbyte[]
andboolean[][]
would be represented by the verification typesarrayOf(byte)
andarrayOf(arrayOf(boolean))
respectively.
The remaining verification types are described as follows:
The verification types top
, oneWord
, twoWord
, and reference
describe abstract unions of other types, as illustrated above, and are represented in Prolog as atoms.
The verification types uninitialized
, uninitializedThis
, and uninitialized(Offset)
describe references to objects created with new
that have not yet been initialized (2.9.2). uninitialized
and uninitializedThis
are represented with an atom. uninitialized(Offset)
is represented by applying the functor uninitialized
to an argument representing the numerical value of the Offset
.
The verification type null
describes the result of the aconst_null
instruction, and is represented in Prolog as an atom.
The subtyping rules for verification types are as follows.
Subtyping is reflexive.
isAssignable(X, X).
The type top
is a supertype of all other types.
isAssignable(oneWord, top).
isAssignable(twoWord, top).
A type is a subtype of some other type, X, if its direct supertype is a subtype of X.
isAssignable(int, X) :- isAssignable(oneWord, X).
isAssignable(float, X) :- isAssignable(oneWord, X).
isAssignable(long, X) :- isAssignable(twoWord, X).
isAssignable(double, X) :- isAssignable(twoWord, X).
isAssignable(reference, X) :- isAssignable(oneWord, X).
isAssignable(class(_, _), X) :- isAssignable(reference, X).
isAssignable(nullfree(_,_), X) :- isAssignable(reference, X).
isAssignable(arrayOf(_), X) :- isAssignable(reference, X).
isAssignable(null, X) :- isAssignable(reference, X).
isAssignable(uninitialized, X) :- isAssignable(reference, X).
isAssignable(uninitializedThis, X) :- isAssignable(uninitialized, X).
isAssignable(uninitialized(_), X) :- isAssignable(uninitialized, X).
The type null
is a subtype of all nullable reference types.
isAssignable(null, class(_, _)).
isAssignable(null, arrayOf(_)).
These subtype rules are not necessarily the most obvious formulation of subtyping. There is a clear split between subtyping rules among reference types, and rules for the remaining verification types. The split allows us to state general subtyping relations between reference types and other verification types. These relations hold independently of a reference type's position in the type hierarchy, and help to prevent excessive class loading by a Java Virtual Machine implementation. For example, we do not want to start climbing the superclass hierarchy in response to a query of the form
class(foo, L) <: twoWord
.
We also have a rule that says subtyping is reflexive, so together these rules cover most verification types that are not reference types.
Subtype rules for the reference types are specified recursively with isWideningReference
.
isAssignable(From, To) :- isWideningReference(From, To).
The verifier allows any reference type to be widened to an interface type.
isWideningReference(class(_, _), class(To, L)) :-
loadedClass(To, L, ToClass),
classIsInterface(ToClass).
isWideningReference(arrayOf(_), class(To, L)) :-
loadedClass(To, L, ToClass),
classIsInterface(ToClass).
isWideningReference(nullfree(_,_), class(To, L)) :-
loadedClass(To, L, ToClass),
classIsInterface(ToClass).
This approach is less strict than the Java Programming Language, which will not allow an assignment to an interface unless the value is statically known to implement or extend the interface. The Java Virtual Machine instead uses a run-time check to ensure that invocations of interface methods actually operate on objects that implement the interface (6.5.invokeinterface). But there is no requirement that a reference stored by a local variable of an interface type refers to an object that actually implements that interface.
A nullable class type can be widened to another nullable class type if that type refers to the loaded class or one of its superclasses.
isWideningReference(class(ClassName, L1), class(ClassName, L2)) :-
L1 \= L2,
loadedClass(ClassName, L1, Class),
loadedClass(ClassName, L2, Class).
isWideningReference(class(From, L1), class(To, L2)) :-
From \= To,
loadedClass(From, L1, FromClass),
loadedClass(To, L2, ToClass),
loadedSuperclases(FromClass, Supers),
member(ToClass, Supers).
A null-free inline class type is a subtype of the nullable type for that class and its supertypes.
isWideningReference(nullfree(N, L), class(N, L)).
isWideningReference(nullfree(From, L1), class(To, L2)) :-
isWideningReference(class(From, L1), class(To, L2)).
Array types are subtypes of Object
.
isWideningReference(arrayOf(_), class('java/lang/Object', L)) :-
loadedClass('java/lang/Object', L, ObjectClass),
classDefiningLoader(ObjectClass, BL),
isBootstrapLoader(BL).
Subtyping between arrays of reference type is covariant.
isWideningReference(arrayOf(X), arrayOf(Y)) :-
isWideningReference(X, Y).
Individual bytecode instructions are represented in Prolog as terms whose functor is the name of the instruction and whose arguments are its parsed operands.
For example, an aload instruction is represented as the term
aload(N)
, which includes the indexN
that is the operand of the instruction.
The instructions as a whole are represented as a list of terms of the form:
instruction(Offset, AnInstruction)
For example,
instruction(21, aload(1))
.
The order of instructions in this list must be the same as in the class
file.
Some instructions have operands that refer to entries in the constant_pool
table. If the constant_pool
index of an operand is invalid, or if the constant pool entry at that index does not have a supported form, as described below, the code attribute cannot be parsed, and verification will fail.
Each checkcast, instanceof, anewarray, and multianewarray, and defaultvalue instruction must have an operand that refers to a CONSTANT_Class_info
constant pool entry (4.4.1). This entry is represented with a functor application, where the functor is the instruction name, and the operand is a class
, nullfree
, or arrayOf
verification type (4.10.1.2) representing the referenced class, interface, or array reference type.
A CONSTANT_Class_info
structure that references a class or interface name is interpreted in this context as the nullable type of the referenced class or interface.
For example, a checkcast instruction whose operand refers to a constant pool entry representing the class
String
would be represented ascheckcast(class('java/lang/String', L))
, whereL
is the class loader of the class containing the instruction.
Each new instruction must have an operand that refers to a CONSTANT_Class_info
constant pool entry. This entry is represented with a functor application of the form new(ClassName)
, where ClassName
is the name of the referenced class. (The CONSTANT_Class_info
must not reference an array type a field descriptor.)
For example, a new instruction whose operand refers to a constant pool entry representing the class
Object
would be represented asnew('java/lang/Object')
.
Each getfield, putfield, withfield, getstatic, and putstatic instruction must have an operand that refers to a CONSTANT_Fieldref_info
constant pool entry (4.4.2). This entry is represented with a functor application of the form field(FieldClassName, FieldName, FieldDescriptor)
. FieldClassName
is the name of the class referenced by the class_index
item in the structure. FieldName
and FieldDescriptor
correspond to the name and field descriptor referenced by the name_and_type_index
item of the structure.
For example, a getfield instruction whose operand refers to a constant pool entry representing a field
foo
of typefloat
in classBar
would be represented asgetfield(field('Bar', 'foo', 'F'))
.
Each invokevirtual, invokeinterface, invokespecial, and invokestatic instruction must have an operand that refers to a constant pool entry that references a method. This entry is represented with a functor application, as follows:
method(MethodClassName, MethodName, MethodDescriptor)
for a constant pool entry that is a CONSTANT_Methodref_info
structure (4.4.2).
MethodClassName
is the name of the class referenced by the class_index
item of the structure. MethodName
and MethodDescriptor
correspond to the name and method descriptor referenced by the name_and_type_index
item of the structure.
imethod(MethodIntfName, MethodName, MethodDescriptor)
for a constant pool entry that is a CONSTANT_InterfaceMethodref_info
structure (4.4.2).
MethodIntfName
is the name of the interface referenced by the class_index
item of the structure. MethodName
and MethodDescriptor
correspond to the name and method descriptor referenced by the name_and_type_index
item of the structure.
For example, an invokevirtual instruction whose operand refers to a constant pool entry representing the
hashCode
method in classObject
would be represented asinvokevirtual(method('java/lang/Object', 'hashCode', '()I'))
.
Each invokedynamic instruction must have an operand that refers to a CONSTANT_InvokeDynamic_info
constant pool entry (4.4.10). This entry is represented with a functor application of the form dmethod(CallSiteName, MethodDescriptor)
.
CallSiteName
and MethodDescriptor
correspond to the name and method descriptor referenced by the name_and_type_index
item of the structure. (The bootstrap_method_attr_index
item is irrelevant to verification.)
Each ldc, ldc_w, and ldc2_w instruction must have an operand that refers to a loadable entry in the constant_pool
table. There are nine kinds of loadable entry (see Table 4.4-C), represented by functor applications of the following forms:
int(Value)
for a constant pool entry that is a CONSTANT_Integer_info
structure (4.4.4).
Value
is the int
constant represented by the bytes
item of the structure.
For example, an ldc instruction for loading the
int
constant 91 would be represented asldc(int(91))
.
float(Value)
for a constant pool entry that is a CONSTANT_Float_info
structure (4.4.4).
Value
is the float
constant represented by the bytes
item of the structure.
long(Value)
for a constant pool entry that is a CONSTANT_Long_info
structure (4.4.5).
Value
is the long
constant represented by the high_bytes
and low_bytes
items of the structure.
double(Value)
for a constant pool entry that is a CONSTANT_Double_info
structure (4.4.5).
Value
is the double
constant represented by the high_bytes
and low_bytes
items of the structure.
class(ClassName, Loader)
, nullfree(ClassName, Loader)
, or arrayOf(Component)
for a constant pool entry that is a CONSTANT_Class_info
structure (4.4.1).
The class
, nullfree
, and arrayOf
functors are defined in 4.10.1.2.
A CONSTANT_Class_info
structure that references a class or interface name is interpreted in this context as the nullable type of the referenced class or interface.
string(Value)
for a constant pool entry that is a CONSTANT_String_info
structure (4.4.3).
Value
is the string referenced by the string_index
item of the structure.
methodHandle(Kind, Reference)
for a constant pool entry that is a CONSTANT_MethodHandle_info
structure (4.4.8).
Kind
is the value of the reference_kind
item of the structure. Reference
is the value of the reference_index
item of the structure.
methodType(MethodDescriptor)
for a constant pool entry that is a CONSTANT_MethodType_info
structure (4.4.9).
MethodDescriptor
is the method descriptor referenced by the descriptor_index
item of the structure.
dconstant(ConstantName, FieldDescriptor)
for a constant pool entry that is a CONSTANT_Dynamic_info
structure (4.4.10).
ConstantName
and FieldDescriptor
correspond to the name and field descriptor referenced by the name_and_type_index
item of the structure. (The bootstrap_method_attr_index
item is irrelevant to verification.)
To interpret method invocation instructions, the following predicates identify references to methods that are instance, class, or interface initialization methods.
isInitReference(MethodRef) :-
MethodRef = method(_, '<init>', MethodDescriptor),
parseMethodDescriptor(MethodDescriptor, _, void).
isInitReference(MethodRef) :-
MethodRef = imethod(_, '<init>', MethodDescriptor),
parseMethodDescriptor(MethodDescriptor, _, void).
isClinitReference(MethodRef) :-
MethodRef = method(_, '<clinit>', MethodDescriptor),
parseMethodDescriptor(MethodDescriptor, [], void).
isClinitReference(MethodRef) :-
MethodRef = imethod(_, '<clinit>', MethodDescriptor),
parseMethodDescriptor(MethodDescriptor, [], void).
Non-abstract
, non-native
methods are type correct if they have code and the code is type correct.
methodIsTypeSafe(Class, Method) :-
doesNotOverrideFinalMethod(Class, Method),
methodAccessFlags(Method, AccessFlags),
methodAttributes(Method, Attributes),
notMember(native, AccessFlags),
notMember(abstract, AccessFlags),
member(attribute('Code', _), Attributes),
methodWithCodeIsTypeSafe(Class, Method).
A method with code is type safe if it is possible to merge the code and the stack map frames into a single stream such that each stack map frame precedes the instruction it corresponds to, and the merged stream is type correct. The method's exception handlers, if any, must also be legal.
methodWithCodeIsTypeSafe(Class, Method) :-
parseCodeAttribute(Class, Method, FrameSize, MaxStack,
ParsedCode, Handlers, StackMap),
mergeStackMapAndCode(StackMap, ParsedCode, MergedCode),
methodInitialStackFrame(Class, Method, FrameSize, StackFrame, ReturnType),
Environment = environment(Class, Method, ReturnType, MergedCode,
MaxStack, Handlers),
handlersAreLegal(Environment),
mergedCodeIsTypeSafe(Environment, MergedCode, StackFrame).
Let us consider exception handlers first.
An exception handler is represented by a functor application of the form:
handler(Start, End, Target, ClassName)
whose arguments are, respectively, the start and end of the range of instructions covered by the handler, the first instruction of the handler code, and the name of the exception class that this handler is designed to handle.
An exception handler is legal if its start (Start
) is less than its end (End
), there exists an instruction whose offset is equal to Start
, there exists an instruction whose offset equals End
, and the handler's exception class is assignable to the class Throwable
. The exception class of a handler is Throwable
if the handler's class entry is 0, otherwise it is the class named in the handler.
An additional requirement exists for a handler inside an instance initialization method if one of the instructions covered by the handler is invokespecial of an instance initialization method. In this case, the fact that a handler is running means the object under construction is likely broken, so it is important that the handler does not swallow the exception and allow the enclosing instance initialization method to return normally to the caller. Accordingly, the handler is required to either complete abruptly by throwing an exception to the caller of the enclosing instance initialization method, or to loop forever.
handlersAreLegal(Environment) :-
exceptionHandlers(Environment, Handlers),
checklist(handlerIsLegal(Environment), Handlers).
handlerIsLegal(Environment, Handler) :-
Handler = handler(Start, End, Target, _),
Start < End,
allInstructions(Environment, Instructions),
member(instruction(Start, _), Instructions),
offsetStackFrame(Environment, Target, _),
instructionsIncludeEnd(Instructions, End),
currentClassLoader(Environment, CurrentLoader),
handlerExceptionClass(Handler, ExceptionClass, CurrentLoader),
isBootstrapLoader(BL),
isAssignable(ExceptionClass, class('java/lang/Throwable', BL)),
initHandlerIsLegal(Environment, Handler).
instructionsIncludeEnd(Instructions, End) :-
member(instruction(End, _), Instructions).
instructionsIncludeEnd(Instructions, End) :-
member(endOfCode(End), Instructions).
handlerExceptionClass(handler(_, _, _, 0),
class('java/lang/Throwable', BL), _) :-
isBootstrapLoader(BL).
handlerExceptionClass(handler(_, _, _, Name),
class(Name, L), L) :-
Name \= 0.
initHandlerIsLegal(Environment, Handler) :-
notInitHandler(Environment, Handler).
notInitHandler(Environment, Handler) :-
Environment = environment(_Class, Method, _, Instructions, _, _),
isNotInit(Method).
notInitHandler(Environment, Handler) :-
Environment = environment(_Class, Method, _, Instructions, _, _),
isInit(Method),
member(instruction(_, invokespecial(CP)), Instructions),
\+ isInitReference(CP).
initHandlerIsLegal(Environment, Handler) :-
isInitHandler(Environment, Handler),
sublist(isApplicableInstruction(Target), Instructions,
HandlerInstructions),
noAttemptToReturnNormally(HandlerInstructions).
isInitHandler(Environment, Handler) :-
Environment = environment(_Class, Method, _, Instructions, _, _),
isInit(Method).
member(instruction(_, invokespecial(CP)), Instructions),
isInitReference(CP).
isApplicableInstruction(HandlerStart, instruction(Offset, _)) :-
Offset >= HandlerStart.
noAttemptToReturnNormally(Instructions) :-
notMember(instruction(_, return), Instructions).
noAttemptToReturnNormally(Instructions) :-
member(instruction(_, athrow), Instructions).
Let us now turn to the stream of instructions and stack map frames.
Merging instructions and stack map frames into a single stream involves four cases:
Merging an empty StackMap
and a list of instructions yields the original list of instructions.
mergeStackMapAndCode([], CodeList, CodeList).
Given a list of stack map frames beginning with the type state for the instruction at Offset
, and a list of instructions beginning at Offset
, the merged list is the head of the stack map frame list, followed by the head of the instruction list, followed by the merge of the tails of the two lists.
mergeStackMapAndCode([stackMap(Offset, Map) | RestMap],
[instruction(Offset, Parse) | RestCode],
[stackMap(Offset, Map),
instruction(Offset, Parse) | RestMerge]) :-
mergeStackMapAndCode(RestMap, RestCode, RestMerge).
Otherwise, given a list of stack map frames beginning with the type state for the instruction at OffsetM
, and a list of instructions beginning at OffsetP
, then, if OffsetP < OffsetM
, the merged list consists of the head of the instruction list, followed by the merge of the stack map frame list and the tail of the instruction list.
mergeStackMapAndCode([stackMap(OffsetM, Map) | RestMap],
[instruction(OffsetP, Parse) | RestCode],
[instruction(OffsetP, Parse) | RestMerge]) :-
OffsetP < OffsetM,
mergeStackMapAndCode([stackMap(OffsetM, Map) | RestMap],
RestCode, RestMerge).
Otherwise, the merge of the two lists is undefined. Since the instruction list has monotonically increasing offsets, the merge of the two lists is not defined unless every stack map frame offset has a corresponding instruction offset and the stack map frames are in monotonically increasing order.
To determine if the merged stream for a method is type correct, we first infer the method's initial type state.
The initial type state of a method consists of an empty operand stack and local variable types derived from the type of this
and the arguments, as well as the appropriate flag, depending on whether this is an instance initialization method.
methodInitialStackFrame(Class, Method, FrameSize, frame(Locals, [], Flags),
ReturnType):-
methodDescriptor(Method, Descriptor),
parseMethodDescriptor(Descriptor, RawArgs, ReturnType),
expandTypeList(RawArgs, Args),
methodInitialThisType(Class, Method, ThisList),
flags(ThisList, Flags),
append(ThisList, Args, ThisArgs),
expandToLength(ThisArgs, FrameSize, top, Locals).
Given a list of types, the following clause produces a list where every type of size 2 has been substituted by two entries: one for itself, and one top
entry. The result then corresponds to the representation of the list as 32-bit words in the Java Virtual Machine.
expandTypeList([], []).
expandTypeList([Item | List], [Item | Result]) :-
sizeOf(Item, 1),
expandTypeList(List, Result).
expandTypeList([Item | List], [Item, top | Result]) :-
sizeOf(Item, 2),
expandTypeList(List, Result).
flags([uninitializedThis], [flagThisUninit]).
flags(X, []) :- X \= [uninitializedThis].
expandToLength(List, Size, _Filler, List) :-
length(List, Size).
expandToLength(List, Size, Filler, Result) :-
length(List, ListLength),
ListLength < Size,
Delta is Size - ListLength,
length(Extra, Delta),
checklist(=(Filler), Extra),
append(List, Extra, Result).
For the initial type state of an instance method, we compute the type of this
and put it in a list. The type of this
in the instance initialization method of Object
is Object
; in other instance initialization methods, the type of this
is uninitializedThis
; **the type of this
in an instance method of an inline class is nullfree(N, L)
, where N
is the name of the class containing the method and L
is its defining class loader; otherwise, the type of this
in an instance method is class(N, L)
where .N
is the name of the class containing the method and L
is its defining class loader
For the initial type state of a static method, this
is irrelevant, so the list is empty.
methodInitialThisType(_Class, Method, []) :-
methodAccessFlags(Method, AccessFlags),
member(static, AccessFlags).
methodInitialThisType(Class, Method, [This]) :-
methodAccessFlags(Method, AccessFlags),
notMember(static, AccessFlags),
instanceMethodInitialThisType(Class, Method, This).
instanceMethodInitialThisType(Class, Method, class('java/lang/Object', L)) :-
isInit(Method),
classDefiningLoader(Class, L),
isBootstrapLoader(L),
classClassName(Class, 'java/lang/Object').
instanceMethodInitialThisType(Class, Method, uninitializedThis) :-
isInit(Method),
loadedSuperclasses(Class, Supers),
Supers \= [].
instanceMethodInitialThisType(Class, Method, class(ClassName, L)) :-
isNotInit(Method),
classDefiningLoader(Class, L),
classClassName(Class, ClassName).
instanceMethodInitialThisType(Class, Method, nullfree(ClassName, L)) :-
classIsInline(Class),
classDefiningLoader(Class, L),
classClassName(Class, ClassName).
instanceMethodInitialThisType(Class, Method, class(ClassName, L)) :-
isNotInit(Method),
\+ classIsInline(Class),
classDefiningLoader(Class, L),
classClassName(Class, ClassName).
We now compute whether the merged stream for a method is type correct, using the method's initial type state:
If we have a stack map frame and an incoming type state, the type state must be assignable to the one in the stack map frame. We may then proceed to type check the rest of the stream with the type state given in the stack map frame.
mergedCodeIsTypeSafe(Environment, [stackMap(Offset, MapFrame) | MoreCode],
frame(Locals, OperandStack, Flags)) :-
frameIsAssignable(frame(Locals, OperandStack, Flags), MapFrame),
mergedCodeIsTypeSafe(Environment, MoreCode, MapFrame).
A merged code stream is type safe relative to an incoming type state T
if it begins with an instruction I
that is type safe relative to T
, and I
satisfies its exception handlers (see below), and the tail of the stream is type safe given the type state following that execution of I
.
NextStackFrame
indicates what falls through to the following instruction. For an unconditional branch instruction, it will have the special value afterGoto
. ExceptionStackFrame
indicates what is passed to exception handlers.
mergedCodeIsTypeSafe(Environment, [instruction(Offset, Parse) | MoreCode],
frame(Locals, OperandStack, Flags)) :-
instructionIsTypeSafe(Parse, Environment, Offset,
frame(Locals, OperandStack, Flags),
NextStackFrame, ExceptionStackFrame),
instructionSatisfiesHandlers(Environment, Offset, ExceptionStackFrame),
mergedCodeIsTypeSafe(Environment, MoreCode, NextStackFrame).
After an unconditional branch (indicated by an incoming type state of afterGoto
), if we have a stack map frame giving the type state for the following instructions, we can proceed and type check them using the type state provided by the stack map frame.
mergedCodeIsTypeSafe(Environment, [stackMap(Offset, MapFrame) | MoreCode],
afterGoto) :-
mergedCodeIsTypeSafe(Environment, MoreCode, MapFrame).
It is illegal to have code after an unconditional branch without a stack map frame being provided for it.
mergedCodeIsTypeSafe(_Environment, [instruction(_, _) | _MoreCode],
afterGoto) :-
write_ln('No stack frame after unconditional branch'),
fail.
If we have an unconditional branch at the end of the code, stop.
mergedCodeIsTypeSafe(_Environment, [endOfCode(Offset)],
afterGoto).
Branching to a target is type safe if the target has an associated stack frame, Frame
, and the current stack frame, StackFrame
, is assignable to Frame
.
targetIsTypeSafe(Environment, StackFrame, Target) :-
offsetStackFrame(Environment, Target, Frame),
frameIsAssignable(StackFrame, Frame).
An instruction satisfies its exception handlers if it satisfies every exception handler that is applicable to the instruction.
instructionSatisfiesHandlers(Environment, Offset, ExceptionStackFrame) :-
exceptionHandlers(Environment, Handlers),
sublist(isApplicableHandler(Offset), Handlers, ApplicableHandlers),
checklist(instructionSatisfiesHandler(Environment, ExceptionStackFrame),
ApplicableHandlers).
An exception handler is applicable to an instruction if the offset of the instruction is greater or equal to the start of the handler's range and less than the end of the handler's range.
isApplicableHandler(Offset, handler(Start, End, _Target, _ClassName)) :-
Offset >= Start,
Offset < End.
An instruction satisfies an exception handler if the instructions's outgoing type state is ExcStackFrame
, and the handler's target (the initial instruction of the handler code) is type safe assuming an incoming type state T
. The type state T
is derived from ExcStackFrame
by replacing the operand stack with a stack whose sole element is the handler's exception class.
instructionSatisfiesHandler(Environment, ExcStackFrame, Handler) :-
Handler = handler(_, _, Target, _),
currentClassLoader(Environment, CurrentLoader),
handlerExceptionClass(Handler, ExceptionClass, CurrentLoader),
/* The stack consists of just the exception. */
ExcStackFrame = frame(Locals, _, Flags),
TrueExcStackFrame = frame(Locals, [ ExceptionClass ], Flags),
operandStackHasLegalLength(Environment, TrueExcStackFrame),
targetIsTypeSafe(Environment, TrueExcStackFrame, Target).
An anewarray instruction with operand CP
is type safe iff CP
refers to a constant pool entry denoting a class, an interface, or an array a reference type, and one can legally replace a type matching int
on the incoming operand stack with an array with component type CP
yielding the outgoing type state.
instructionIsTypeSafe(anewarray(CP), Environment, _Offset, StackFrame,
NextStackFrame, ExceptionStackFrame) :-
validTypeTransition(Environment, [int], arrayOf(CP),
StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
A checkcast instruction with operand CP
is type safe iff CP
refers to a constant pool entry denoting a class, an interface, or an array a reference type, and one can validly replace the type Object
on top of the incoming operand stack with the type denoted by CP
yielding the outgoing type state.
instructionIsTypeSafe(checkcast(CP), Environment, _Offset, StackFrame,
NextStackFrame, ExceptionStackFrame) :-
isBootstrapLoader(BL),
validTypeTransition(Environment, [class('java/lang/Object', BL)], CP,
StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
A defaultvalue instruction with operand CP
is type safe iff CP
refers to a constant pool entry denoting a null-free inline class type, and and one can validly push type CP
onto the incoming operand stack yielding the outgoing type state.
instructionIsTypeSafe(defaultvalue(CP), Environment, _Offset, StackFrame,
NextStackFrame, ExceptionStackFrame) :-
CP = nullfree(_,_),
validTypeTransition(Environment, [], CP, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
An instanceof instruction with operand CP
is type safe iff CP
refers to a constant pool entry denoting a class, an interface, or an array a reference type, and one can validly replace the type Object
on top of the incoming operand stack with type int
yielding the outgoing type state.
instructionIsTypeSafe(instanceof(CP), Environment, _Offset, StackFrame,
NextStackFrame, ExceptionStackFrame) :-
isBootstrapLoader(BL),
validTypeTransition(Environment, [class('java/lang/Object', BL)], int,
StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
A withfield instruction with operand CP
is type safe iff its operand, CP
, refers to a constant pool entry denoting a field whose declared type is FieldType
, declared in a class FieldClassName
; and one can validly replace types matching FieldType
and the nullable type of FieldClassName
with the null-free type of FieldClassName
on the incoming operand stack, yielding the outgoing type state.
instructionIsTypeSafe(withfield(CP), Environment, _Offset, StackFrame,
NextStackFrame, ExceptionStackFrame) :-
CP = field(FieldClassName, FieldName, FieldDescriptor),
parseFieldDescriptor(FieldDescriptor, FieldType),
currentClassLoader(Environment, CurrentLoader),
validTypeTransition(Environment,
[FieldType, class(FieldClassName, CurrentLoader)],
nullfree(FieldClassName, CurrentLoader),
StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
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, interface, or array reference type is derived from a CONSTANT_Class_info
structure (4.4.1). Such a reference gives the name of a class or interface, or the field descriptor representation of an array a reference type, as described in 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 or interface 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 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 interface 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 class String
, and is derived from a CONSTANT_String_info
structure (4.4.3). To derive a string constant, the Java Virtual Machine examines the sequence of code points given by the CONSTANT_String_info
structure:
If the method String.intern
has previously been invoked on an instance of class String
containing a sequence of Unicode code points identical to that given by the CONSTANT_String_info
structure, then the string constant is a reference
to that same instance of class String
.
Otherwise, a new instance of class String
is created containing the sequence of Unicode code points given by the CONSTANT_String_info
structure. The string constant is a reference
to the new instance. Finally, the method String.intern
is invoked on the new instance.
Numeric constants are derived from CONSTANT_Integer_info
, CONSTANT_Float_info
, CONSTANT_Long_info
, and CONSTANT_Double_info
structures (4.4.4, 4.4.5).
Note that CONSTANT_Float_info
structures represent values in IEEE 754 single format and CONSTANT_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, interfaces, and array reference types
Symbolic references to method handles
Symbolic references to method types
Symbolic references to dynamically-computed constants
Static constants
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 imposes constraints on field and method descriptors (4.3), as follows:
For each occurrence of a NullFreeClassType in a descriptor of a field or method declared by C, the defining class loader of C is used to create the referenced class or interface.
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 preparation.
If the result of creation is not an inline class, preparation fails with an IncompatibleClassChangeError
.
For each field of C with a null-free inline class type, the type is resolved, as if by resolution of an unresolved symbolic reference to a reference type (5.4.3.1), and the named inline class is prepared.
Any exception that can be thrown as a result of failure of reference type resolution can thus be thrown as a result of failure of preparation.
If preparation of the inline class recursively requires preparation of the class C, preparation fails with a ClassCircularityError
.
An inline class instance is not allowed to "contain" another instance of the same class in a "flattened" form, because the instance could have no finite "flattened" representation. Fields with nullable inline class types are not intended to support "flattening" in this way, and so are not subject to this constraint.
After preparation of C, a field of C with a null-free inline class type will hold the default value instance of that inline class. This step ensures that the class has access to create the default value, and that the class of the default value has been prepared.
Note the distinction between steps (1) and (2): step (1) applies to any null-free inline class type appearing in a field or method descriptor, while step (2) only applies to a null-free inline class type that is the type of a field. As a result, an inaccessible null-free inline class type may be used in a method descriptor, or as an array component type in a field descriptor, but may not be used as the type of a field.
Preparation must occur for the inline class before any user code attempts to access the default value. We guarantee this by recursively preparing the referenced class. Ideally, initialization will occur as well, per 5.5, before user code accesses the field. But user code may execute during initialization before initialization has a chance to handle the field, so we can't guarantee it.
Design discussion: the circularity check on field types should eventually be dropped for static
fields, but there are outstanding tricky issues to work out.
An alternative design could permit circularities among instance fields, and require the JVM to infer whether such circularities preclude flattening of the field.
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>
, for 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.
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. For each class or interface name N mentioned by the descriptor of m, the Java Virtual Machine imposes the loading constraint NL2 = NL3.
Preparation may occur at any time following creation but must be completed prior to initialization.
Many Java Virtual Machine instructions - anewarray, checkcast, defaultvalue, getfield, getstatic, instanceof, invokedynamic, invokeinterface, invokespecial, invokestatic, invokevirtual, ldc, ldc_w, ldc2_w, multianewarray, new, putfield, and putstatic, and withfield - 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, interface, or array reference 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. In the first three of those sections, the class or interface in whose run-time constant pool the symbolic reference appears is labeled D. Then:
If no error occurs during resolution of the symbolic reference, then resolution succeeds.
Subsequent attempts to resolve the symbolic reference always succeed trivially and result in the same entity produced by the initial resolution. If the symbolic reference is to a dynamically-computed constant, the bootstrap method is not re-executed for these subsequent attempts.
IncompatibleClassChangeError
(or a subclass);
Error
(or a subclass) that arose from resolution or invocation of a bootstrap method; or (iii) an instance of LinkageError
(or a subclass) that arose because class loading failed or a loader constraint was violated. The error must be thrown at a point in the program that (directly or indirectly) uses the symbolic reference.Subsequent attempts to resolve the symbolic reference always fail with the same error that was thrown as a result of the initial resolution attempt. If the symbolic reference is to a dynamically-computed constant, the bootstrap method is not re-executed for these subsequent attempts.
Because errors occurring on an initial attempt at resolution are thrown again on subsequent attempts, a class in one module that attempts to access, via resolution of a symbolic reference in its run-time constant pool, an unexported
public
type in a different module will always receive the same error indicating an inaccessible type (5.4.4), even if the Java SE Platform API is used to dynamically export thepublic
type's package at some time after the class's first attempt.
Resolution of an unresolved symbolic reference to a dynamically-computed call site proceeds in accordance with the rules given in 5.4.3.6. Then:
If no error occurs during resolution of the symbolic reference, then resolution succeeds solely for the instruction in the class
file that required resolution. This instruction necessarily has an opcode of invokedynamic.
Subsequent attempts to resolve the symbolic reference by that instruction in the class
file always succeed trivially and result in the same entity produced by the initial resolution. The bootstrap method is not re-executed for these subsequent attempts.
The symbolic reference is still unresolved for all other instructions in the class
file, of any opcode, which indicate the same entry in the run-time constant pool as the invokedynamic instruction above.
IncompatibleClassChangeError
(or a subclass);
Error
(or a subclass) that arose from resolution or invocation of a bootstrap method; or (iii) an instance of LinkageError
(or a subclass) that arose because class loading failed or a loader constraint was violated. The error must be thrown at a point in the program that (directly or indirectly) uses the symbolic reference.Subsequent attempts by the same instruction in the class
file to resolve the symbolic reference always fail with the same error that was thrown as a result of the initial resolution attempt. The bootstrap method is not re-executed for these subsequent attempts.
The symbolic reference is still unresolved for all other instructions in the class
file, of any opcode, which indicate the same entry in the run-time constant pool as the invokedynamic instruction above.
Certain of the instructions above require additional linking checks when resolving symbolic references. For instance, in order for a getfield instruction to successfully resolve the symbolic reference to the field on which it operates, it must not only complete the field resolution steps given in 5.4.3.2 but also check that the field is not static
. If it is a static
field, a linking exception must be thrown.
Linking exceptions generated by checks that are specific to the execution of a particular Java Virtual Machine instruction are given in the description of that instruction and are not covered in this general discussion of resolution. Note that such exceptions, although described as part of the execution of Java Virtual Machine instructions rather than resolution, are still properly considered failures of 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.
Access control is applied for the access from D to C (5.4.4).
To resolve an unresolved symbolic reference from D to an array a reference type T, the following steps are performed:
If the element type of the array type is a class or interface type For any class or interface name N mentioned by the symbolic reference's descriptor (4.3.2), the named class or interface N is resolved, as if by resolution of an unresolved symbolic reference to the named a class or interface N.
For any occurrence of a NullFreeClassType in the descriptor, if the resolved class is not an inline class, resolution fails with an IncompatibleClassChangeError
.
A representation of the array reference type denoted by the symbolic reference is created.
If resolution of a class, interface, or array reference 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.
Design discussion: we tentatively allow malformed types like Qjava/lang/String;
to appear in field and method references, even though we prohibit them here in types that are resolved. Since it's impossible to declare a field or method with such a type (see 5.4.2), resolution of these field and method references will fail anyway. But we could be more strict and perform the same check. In practice, this would mean an IncompatibleClassChangeError
replaces a NoSuchFieldError
or NoSuchMethodError
. (Extra class loading would be called for, too, but if a matching field/method exists, it has already loaded the named class.)
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 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 reference to a class or interface can thus be thrown as a result of failure of method type resolution.
For each occurrence of a NullFreeClassType in the method descriptor, if the resolved class is not an inline class, resolution fails with an IncompatibleClassChangeError
.
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 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 a field or method given by MH.
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.
Let C be the class or interface referenced by R.
Let T be the type given by the field referenced by descriptor of R, or the return type given by the method descriptor of R. Let A* be the sequence (perhaps empty) of parameter types given by the method descriptor of R.
To resolve MH, all symbolic references to classes, interfaces, 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, or Object
.
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
, and REF_invokeVirtual
): If C.f
or C.m
resolved to a protected
field or method, and C is in a different run-time package than the current class, then C must be assignable to the current class.
For kind 8 (REF_newInvokeSpecial
): If C .
<init>
resolved to a protected
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
, and REF_invokeInterface
): C.f
or C.m
must resolve to a non-static
field or method.
For kinds 2, 4, and 6 (REF_getStatic
, REF_putStatic
, and REF_invokeStatic
): C.f
or C.m
must resolve to a static
field or method.
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 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, or method type 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.
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, defaultvalue, anewarray, multianewarray, getstatic, putstatic, or invokestatic that references C (6.5.new, 6.5.defaultvalue, 6.5.anewarray, 6.5.multianewarray, 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 defaultvalue instruction, the class to be initialized is the class named by the referenced null-free inline class type.
Upon execution of an anewarray instruction, if the instruction references a null-free inline class type, the class to be initialized is the named inline class.
Upon execution of a multianewarray instruction, if the instruction references an array type whose element type is a null-free inline class type, and the dimensions operand of the instruction matches the number of dimensions of the array type, the class to be initialized is the named inline class.
Design discussion: it is only strictly necessary to initialize the inline class if the anewarray or multianewarray actually allocates an array of the null-free type. We could skip initialization for allocations of 0-length arrays, but doing so would tie the initialization logic to dynamic values, which may not be wanted. We could also initialize more eagerly, whenever anewarray or multianewarray creates an array with an inline class element type, regardless of the number of dimensions.
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 package java.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.
If C is an inline class, the initialization of a class that declares a field whose type is the null-free type of C.
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 or interface contains state that indicates one of four situations:
This class or interface is verified and prepared but not initialized.
This class or interface is being initialized by some particular thread.
This class or interface is fully initialized and ready for use.
This class or interface is in an erroneous state, perhaps because initialization was attempted and failed.
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 C 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.
Thread interrupt status is unaffected by execution of the initialization procedure.
If C 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.
If C indicates that it has already been initialized, then no further action is required. Release LC and complete normally.
If C is in an erroneous state, then initialization is not possible. Release LC and throw a NoClassDefFoundError
.
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 its ConstantValue
attribute (4.7.2), in the order the fields appear in the ClassFile
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 the interfaces
array of C), the enumeration recurs on I's superinterfaces (in the order of the interfaces
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 C as erroneous, notify all waiting threads, release LC, and complete abruptly, throwing the same exception that resulted from initializing S.
Next, for each field of C (in the order of the fields
array of C), if the field has a null-free inline class type referencing a class F, recursively perform this entire procedure for F. If necessary, verify and prepare F first.
Initialization of F is necessary because the initial value of the field is the default value instance of F.
If the initialization of F completes abruptly because of a thrown exception, then acquire LC, label C as erroneous, notify all waiting threads, release LC, and complete abruptly, throwing the same exception that resulted from initializing F.
Next, determine whether assertions are enabled for C by querying its defining class loader.
Next, execute the class or interface initialization method of C.
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 class ExceptionInInitializerError
with E as the argument, and use this object in place of E in the following step. If a new instance of ExceptionInInitializerError
cannot be created because an OutOfMemoryError
occurs, then use an OutOfMemoryError
object in place of E in the following step.
Acquire LC, label C 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.
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.
Store into reference
array
aastore
aastore = 83 (0x53)
..., arrayref, index, value →
...
The arrayref must be of type reference
and must refer to an array whose components are of type reference
. The index must be of type int
, and value must be of type reference
. The arrayref, index, and value are popped from the operand stack.
If value is null
and the component type of the array referenced by arrayref is not a null-free inline class type, then value is stored as the component of the array at index.
Otherwise, value is non- If value is a non-null value of the component type of the array referenced by arrayref, then value is stored as the component of the array at index.null
.
Whether value is a value of the array component type is determined according to the rules given for checkcast.
If arrayref is null
, aastore throws a NullPointerException
.
Otherwise, if index is not within the bounds of the array referenced by arrayref, the aastore instruction throws an ArrayIndexOutOfBoundsException
.
Otherwise, if value is null
and the component type of the array referenced by arrayref is a null-free inline class type, aastore throws a NullPointerException
.
Otherwise, if the non-null
value is not a value of the array component type, aastore throws an ArrayStoreException
.
Create new array of reference
anewarray
indexbyte1
indexbyte2
anewarray = 189 (0xbd)
..., count →
..., arrayref
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, interface, or array reference type.
The named class, interface, or array reference type is resolved (5.4.3.1). An array component type is derived from the symbolic reference: if the symbolic reference is to a class or interface, the array component type is the nullable type of the referenced class or interface; if the symbolic reference is to a reference type, the array component type is the resolved type.
If the array component type is a null-free inline class type, the resolved class named by the type is initialized if it has not already been initialized (5.5).
A new array with component type given by the resolved class, interface, or array type with the given component type, of length count, is allocated from the garbage-collected heap, and a reference
arrayref to this new array object is pushed onto the operand stack. All components of the new array are initialized to the default value null
,for of the component type (2.4).reference
types
During resolution of the symbolic reference to the class, interface, or array reference type, any of the exceptions documented in 5.4.3.1 can be thrown.
Otherwise, if execution of this anewarray instruction causes initialization of a referenced inline class, anewarray may throw an Error
as detailed in 5.5.
Otherwise, if count is less than zero, the anewarray instruction throws a NegativeArraySizeException
.
The anewarray instruction is used to create a single dimension of an array of object references or part of a multidimensional array.
Check whether object is of given type
checkcast
indexbyte1
indexbyte2
checkcast = 192 (0xc0)
..., objectref →
..., objectref
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, interface, or array reference type.
If objectref is null
and the symbolic reference does not name a null-free inline class type, then the operand stack is unchanged.
Otherwise If objectref is not null
, the named class, interface, or array reference type is resolved (5.4.3.1). A checked type is derived from the symbolic reference: if the symbolic reference is to a class or interface, the checked type is the nullable type of the referenced class or interface; if the symbolic reference is to a reference type, the checked type is the resolved type. If objectref is a value of the type given by the resolved class, interface, or array type checked type, the operand stack is unchanged.
The following rules are used to determine whether a reference to an object is a value of a reference type, T.
If the reference is to an instance of a class C, then:
If T is the Object
type, then the reference is a value of T.
If T is the type of a class 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 the type of an interface I, then the reference is a value of T if C implements I.
If the reference is to an array with component type SC, then:
If T is a class type the Object
type, then the reference is a value of T if T is .Object
If T is an interface type, then the reference is a value of T if T is Cloneable
or java.io.Serializable
(as loaded by the bootstrap class loader).
If T is an array type TC[]
, that is, an array of components of type TC, then the reference is a value of T if one of the following are true:
TC and SC are the same type.
TC is the class type Object
type.
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 a nullable inline class type and SC is the null-free type of the same class.
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
or java.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.
During resolution of the symbolic reference to the class, interface, or array reference type, any of the exceptions documented in 5.4.3.1 can be thrown.
Otherwise, if objectref is null and the symbolic reference names a null-free inline class type, the checkcast instruction throws a NullPointerException
.
Otherwise, if objectref is not null and is not a value of the type given by the resolved class, interface, or array type checked type, the checkcast instruction throws a ClassCastException
.
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.
Push default value of a null-free type
defaultvalue
indexbyte1
indexbyte2
defaultvalue = 203 (0xcb)
... →
..., objectref
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 null-free inline class type.
The referenced type is resolved (5.4.3.1). The named inline class is initialized if it has not already been initialized (5.5).
A reference
to an instance of the inline class, with instance variable values set to the default initial values of their types (2.3, 2.4), is pushed onto the operand stack. Memory for the class instance may be newly allocated from the garbage-collected heap, or may have been allocated previously.
During resolution of the symbolic reference to the null-free inline class type, any of the exceptions documented in 5.4.3.1 can be thrown.
Otherwise, if execution of this defaultvalue instruction causes initialization of the referenced class, defaultvalue may throw an Error
as detailed in 5.5.
The defaultvalue instruction is similar to the new instruction. But unlike new, the class instance created by defaultvalue is completely initialized—there is no need to invoke an instance initialization method.
Default value instances of inline classes are also created implicitly when fields or array components with the null-free type of the class are initialized, via new, anewarray, multianewarray, or class preparation (5.4.2). Any class that can successfully resolve a reference to the inline class can also create a default value instance.
The withfield instruction is used to create inline class instances other than the default value instance.
Design discussion: another possible name for this instruction is aconst_default.
We could relax the restriction on the type to include other reference types—the result would always be null
in those cases. Doing so doesn't seem particularly useful, but could become so when combined with a future type parameter feature. If so, since other instructions that operate on types (anewarray, checkcast, instanceof) allow class and interface names, interpreted as nullable types, we should probably allow them with defaultvalue too.
If we don't relax the restriction, then one could argue that there's no need for a null-free class type (QVal;
)—just use an inline class name (Val
). But this would be confusing, because "default value" is a property of a type, not a class—the default value of LVal;
is null
.
Branch if reference
comparison succeeds
if_acmp<cond>
branchbyte1
branchbyte2
if_acmpeq = 165 (0xa5)
if_acmpne = 166 (0xa6)
..., value1, value2 →
...
Both value1 and value2 must be of type reference
. They are both popped from the operand stack and compared. The results of the comparison are as follows:
if_acmpeq succeeds if and only if value1 = value2 value1 and value2 are the same
if_acmpne succeeds if and only if value1 ≠ value2 value1 and value2 are not the same
Two references are the same if one of the following cases applies:
Both references are null
.
Both references are to identity class instances or arrays with the same identity (2.4).
Both references are to instances of the same inline class, with instance fields whose values are all the same. Field values are compared according to the following rules:
For reference-typed fields, these rules are applied recursively.
For fields of type int
, boolean
, char
, byte
, or short
, the values are the same if a comparison via if_icmpeq
would succeed (6.5.if_icmpeq).
For fields of type long
, the values are the same if a comparison via lcmp
would produce 0 (6.5.lcmp).
For fields of type float
, the values are the same if, after applying the conversion defined by the method Float.floatToIntBits
, a comparison via if_icmpeq
would succeed.
For fields of type double
, the values are the same if, after applying the conversion defined by the method Double.doubleToLongBits
, a comparison via lcmp
would produce 0.
If the comparison succeeds, the unsigned branchbyte1 and branchbyte2 are used to construct a signed 16-bit offset, where the offset is calculated to be (branchbyte1 <<
8) | branchbyte2. Execution then proceeds at that offset from the address of the opcode of this if_acmp<cond> instruction. The target address must be that of an opcode of an instruction within the method that contains this if_acmp<cond> instruction.
Otherwise, if the comparison fails, execution proceeds at the address of the instruction following this if_acmp<cond> instruction.
Design discussion: this new behavior carries some performance and security risks. Two instances of a large inline class may take a surprisingly long time to compare. An attacker with the ability to create arbitrary inline class instances can use if_acmpeq to infer the contents of a private
field. But it may be that the best course of action is to educate users about these risks and discourage them from making inappropriate use of inline classes.
Determine if object is of given type
instanceof
indexbyte1
indexbyte2
instanceof = 193 (0xc1)
..., objectref →
..., result
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, interface, or array type.
If objectref is null
, the instanceof instruction pushes an int
result of 0 onto the operand stack.
Otherwise If objectref is not null
, the named class, interface, or array reference type is resolved (5.4.3.1). A checked type is derived from the symbolic reference: if the symbolic reference is to a class or interface, the checked type is the nullable type of the referenced class or interface; if the symbolic reference is to a reference type, the checked type is the resolved type. If objectref is a value of the type given by the resolved class, interface, or array type checked type, the instanceof instruction pushes an int
result of 1 onto the operand stack; otherwise, it pushes an int
result of 0.
Whether objectref is a value of the type given by the resolved class, interface, or array type checked type is determined according to the rules given for checkcast.
During resolution of the symbolic reference to the class, interface, or array reference type, any of the exceptions documented in 5.4.3.1 can be thrown.
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.
Push item from run-time constant pool
ldc
index
ldc = 18 (0x12)
... →
..., value
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
or double
.
A symbolic reference to a dynamically-computed constant whose field descriptor is J
(denoting long
) or D
(denoting double
).
If the run-time constant pool entry is a numeric constant of type int
or float
, then the value of that numeric constant is pushed onto the operand stack as an int
or float
, respectively.
Otherwise, if the run-time constant pool entry is a string constant, that is, a reference
to an instance of class String
, then value, a reference
to that instance, is pushed onto the operand stack.
Otherwise, if the run-time constant pool entry is a symbolic reference to a class, interface, or array reference type, then the symbolic reference is resolved (5.4.3.1) and value, a reference
to the Class
object representing that class, interface, or array reference type, is pushed onto the operand stack. If the symbolic reference is to a class or interface, value represents the nullable type of the referenced class or interface.
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.
During resolution of a symbolic reference, any of the exceptions pertaining to resolution of that kind of symbolic reference can be thrown.
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 type float
in the constant pool (4.4.4) must be taken from the float value set.
Push item from run-time constant pool (wide index)
ldc_w
indexbyte1
indexbyte2
ldc_w = 19 (0x13)
... →
..., value
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
or double
.
A symbolic reference to a dynamically-computed constant whose field descriptor is J
(denoting long
) or D
(denoting double
).
If the run-time constant pool entry is a numeric constant of type int
or float
, 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 reference 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.
During resolution of a symbolic reference, any of the exceptions pertaining to resolution of that kind of symbolic reference can be thrown.
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 type float
in the constant pool (4.4.4) must be taken from the float value set.
Enter monitor for object
monitorenter
monitorenter = 194 (0xc2)
..., objectref →
...
The objectref must be of type reference
.
Each object instance of an identity class, instance of class Object
, and array is associated with a monitor. A monitor is locked if and only if it has an owner. The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref, as follows:
If the entry count of the monitor associated with objectref is zero, the thread enters the monitor and sets its entry count to one. The thread is then the owner of the monitor.
If the thread already owns the monitor associated with objectref, it reenters the monitor, incrementing its entry count.
If another thread already owns the monitor associated with objectref, the thread blocks until the monitor's entry count is zero, then tries again to gain ownership.
If objectref is null
, monitorenter throws a NullPointerException
.
Otherwise, if objectref is an inline class instance, monitorenter throws an IllegalMonitorStateException
.
Design discussion: we might wish, instead, to support inline class instances by associating a monitor with each unique field-value vector. In that approach, two references have the same monitor iff they are acmpeq. There is some risk, though, that unexpected clashes would lead to subtle bugs, and as a matter of best practice we don't think it's appropriate to use inline class instances for locking, because they can't be guaranteed to be unique.
Further discussion may be warranted on the choice of exception type to throw.
A monitorenter instruction may be used with one or more monitorexit instructions (6.5.monitorexit) to implement a synchronized
statement in the Java programming language (3.14). The monitorenter and monitorexit instructions are not used in the implementation of synchronized
methods, although they can be used to provide equivalent locking semantics. Monitor entry on invocation of a synchronized
method, and monitor exit on its return, are handled implicitly by the Java Virtual Machine's method invocation and return instructions, as if monitorenter and monitorexit were used.
The association of a monitor with an object may be managed in various ways that are beyond the scope of this specification. For instance, the monitor may be allocated and deallocated at the same time as the object. Alternatively, it may be dynamically allocated at the time when a thread attempts to gain exclusive access to the object and freed at some later time when no thread remains in the monitor for the object.
The synchronization constructs of the Java programming language require support for operations on monitors besides entry and exit. These include waiting on a monitor (Object.wait
) and notifying other threads waiting on a monitor (Object.notifyAll
and Object.notify
). These operations are supported in the standard package java.lang
supplied with the Java Virtual Machine. No explicit support for these operations appears in the instruction set of the Java Virtual Machine.
Exit monitor for object
monitorexit
monitorexit = 195 (0xc3)
..., objectref →
...
The objectref must be of type reference
.
The thread that executes monitorexit must be the owner of the monitor associated with the instance instance of an identity class, instance of class Object
, or array referenced by objectref.
The thread decrements the entry count of the monitor associated with objectref. If as a result the value of the entry count is zero, the thread exits the monitor and is no longer its owner. Other threads that are blocking to enter the monitor are allowed to attempt to do so.
If objectref is null
, monitorexit throws a NullPointerException
.
Otherwise, if objectref is an inline class instance, monitorexit throws an IllegalMonitorStateException
.
Otherwise, if the thread that executes monitorexit is not the owner of the monitor associated with the instance referenced by objectref, monitorexit throws an IllegalMonitorStateException
.
Otherwise, if the Java Virtual Machine implementation enforces the rules on structured locking described in 2.11.10 and if the second of those rules is violated by the execution of this monitorexit instruction, then monitorexit throws an IllegalMonitorStateException
.
One or more monitorexit instructions may be used with a monitorenter instruction (6.5.monitorenter) to implement a synchronized
statement in the Java programming language (3.14). The monitorenter and monitorexit instructions are not used in the implementation of synchronized
methods, although they can be used to provide equivalent locking semantics.
The Java Virtual Machine supports exceptions thrown within synchronized
methods and synchronized
statements differently:
Monitor exit on normal synchronized
method completion is handled by the Java Virtual Machine's return instructions. Monitor exit on abrupt synchronized
method completion is handled implicitly by the Java Virtual Machine's athrow instruction.
When an exception is thrown from within a synchronized
statement, exit from the monitor entered prior to the execution of the synchronized
statement is achieved using the Java Virtual Machine's exception handling mechanism (3.14).
Create new multidimensional array
multianewarray
indexbyte1
indexbyte2
dimensions
multianewarray = 197 (0xc5)
..., count1, [count2, ...] →
..., arrayref
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 to an array type. The referenced array type is resolved (5.4.3.1). The resulting entry must be an array type of dimensionality greater than or equal to dimensions.
If the array type has a null-free inline class element type, and dimensions matches the number of dimensions of the array type, the inline class is initialized if it has not already been initialized (5.5).
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 component type of that dimension. A reference
arrayref to the new array is pushed onto the operand stack.
During resolution of the symbolic reference to the array type, any of the exceptions documented in 5.4.3.1 can be thrown.
Otherwise, if execution of this multianewarray instruction causes initialization of a referenced inline class, multianewarray may throw an Error
as detailed in 5.5.
Otherwise, if any of the dimensions values on the operand stack are less than zero, the multianewarray instruction throws a NegativeArraySizeException
.
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 type 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.
Create new object
new
indexbyte1
indexbyte2
new = 187 (0xbb)
... →
..., objectref
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 interface. The named class or interface is resolved (5.4.3.1) and should result in a non-abstract
identity class or the class Object
. 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 to the default initial values of their types (2.3, 2.4). The objectref, a reference
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).
During resolution of the symbolic reference to the class or interface, 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, or an inline class, new throws an InstantiationError
.
Otherwise, if execution of this new instruction causes initialization of the referenced class, new may throw an Error
as detailed in 5.5.
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.
Duplicate inline class instance with new field value
withfield
indexbyte1
indexbyte2
withfield = 204 (0xcc)
..., objectref1, value →
..., objectref2
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 in which the field is to be found. The referenced field is resolved (5.4.3.2).
The objectref1 must be an instance of an inline class, and the resolved field must be declared by that class.
The type of a value stored by a withfield instruction must be compatible with the descriptor of the referenced field (4.3.2). If the field descriptor type is boolean
, byte
, char
, short
, or int
, then the value must be an int
. If the field descriptor type is float
, long
, or double
, then the value must be a float
, long
, or double
, respectively. If the field descriptor type is a reference type, then the value must be of a type that is assignment compatible (JLS §5.2) with the field descriptor type.
The resolved field must be declared by a class that belongs to the same nest as the current class, according to the nestmate test in 5.4.4.
The value and objectref1 are popped from the operand stack.
If the value is of type int
and the field descriptor type is boolean
, then the int
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'.
A reference
to an instance of the inline class, objectref2, is pushed onto the operand stack. The referenced field in objectref2 is set to value'. Every other instance field in objectref2 is set to the corresponding field's value in objectref1. Memory for objectref2 may be newly allocated from the garbage-collected heap, or may have been allocated previously.
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, or the resolved field is not declared by an inline class, withfield throws an IncompatibleClassChangeError
.
Otherwise, if the resolved field is not declared by a class that belongs to the same nest as the current class, any of the exceptions pertaining to the nestmate test (5.4.4) may be thrown.
Otherwise, if objectref1 is null
, the withfield instruction throws a NullPointerException
.
Design discussion: the access restriction is intended to limit unauthorized creation of inline class instances. Without it, there would be no way to prevent unauthorized inline class instances with arbitrary public field values. For instance creation outside of the class (and its nestmates), inline classes should declare factory methods with appropriate access restrictions and input validation logic.
However, some inline classes do not care to control instance creation. These classes can declare trivial public factory methods, but we might also want to give their clients direct access to the withfield mechanism. To do so, we would need new accessibility attributes on fields or classes, independent of the "read" access described by ACC_PUBLIC
, etc.