Copyright © 2017 Oracle America, Inc. Legal Notice.
This document proposes changes to the Java Virtual Machine Specification to support a prototype of value classes—classes for which primitive-like non-reference value instances can be created and operated on.
Broad goals of these changes include:
Updating the JVM type system to allow for direct value class types. This includes some incidental changes to address technical debt.
Introducing the ValueCapableClass
attribute and describing how value classes are derived from classes with this attribute.
Allowing version 54.1 class files to refer to direct value class types in their CONSTANT_Class_info
and CONSTANT_NameAndType_info
constant pool entries. Clarifying and decoupling the relationship between classes and types.
vdefault
, vwithfield
, vload
, vstore
, vreturn
, vaload
, vastore
, vbox
, and vunbox
. Describing the structural constraints, verification rules, resolution checks, and run-time behavior of these instructions. Enhancing some other instructions to operate on direct value class types.Like the Java programming language, the The Java Virtual Machine operates on two kinds of types: primitive types direct value 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 direct 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 Direct values need not be tagged or otherwise be inspectable to determine their types at run time, or to be distinguished from reference 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 one or more reference types, including the type reference
Object
. Values of type reference types 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 reference
values of type references.reference
Certain classes may instead support direct value class instances. These class instances are similar to objects, but do not allow field mutation, locking, or other identity-based operations. A direct value class instance has exactly one type, the direct value type of the class it instantiates.
The direct value types are the primitive types and the direct value class types.
The primitive data types supported by the Java Virtual Machine are the numeric types, the boolean
type (2.3.4), and the returnAddress
type (2.3.3).
The numeric types consist of the integral types (2.3.1) and the floating-point types (2.3.2).
...
The values of the boolean
type encode the truth values true
and false
, and the default value is false
.
The First Edition of The Java® Virtual Machine Specification did not consider
boolean
to be a Java Virtual Machine type. However,boolean
values do have limited support in the Java Virtual Machine. The Second Edition of The Java® Virtual Machine Specification clarified the issue by treatingboolean
as a type.
The values of the returnAddress
type are pointers to the opcodes of Java Virtual Machine instructions. Of the primitive types, only the returnAddress
type is not directly associated with a Java programming language type.
Direct value class types are described by value classes. The values of a direct value class type are direct values that are instances of the class. They can be thought of as compositions of values of primitive or reference types, with components stored in fields.
Every value class has a corresponding direct value class type. Value classes are derived from value-capable classes (4.7.25).
The default value of a direct value class type is a class instance whose fields store the default values of their respective types. There is no special null
value of a direct value class type.
There are three kinds of reference types: reference class types, array types, and interface types. Their values are references to dynamically created reference
class instances, arrays, or class instances or arrays that implement interfaces, respectively reference class instances and arrays.
Note that arrays can be instances of the class type Object
. No need to get overly-specific here.
Every class (4.1) that is not a value class has a corresponding reference class type. Every interface (4.1) has a corresponding interface type.
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. 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 some non-array type.
A reference value may also be the special null reference, a reference to no object, which will be denoted here by reference
null
. The null reference initially has no run-time type, but may be cast to any type. The default value of a all reference types is reference
typenull
.
This specification does not mandate a concrete value encoding null
.
The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads. The heap is the run-time data area from which memory for all reference class instances and arrays is allocated. Memory for direct value class instances may also be allocated from the heap (2.7).
...
Each frame (2.6) contains an array of variables known as its local variables. The length of the local variable array of a frame is determined at compile-time and supplied in the binary representation of a class or interface along with the code for the method associated with the frame (4.7.3).
A single local variable can hold a value of type boolean
, byte
, char
, short
,int
, float
, or reference
,returnAddress
; a direct value class instance; or a reference. A pair of local variables can hold a value of type long
or double
.
Local variables are addressed by indexing. The index of the first local variable is zero. An integer is considered to be an index into the local variable array if and only if that integer is between zero and one less than the size of the local variable array.
A value of type long
or type double
occupies two consecutive local variables. Such a value may only be addressed using the lesser index. For example, a value of type double
stored in the local variable array at index n actually occupies the local variables with indices n and n+1; however, the local variable at index n+1 cannot be loaded from. It can be stored into. However, doing so invalidates the contents of local variable n.
The Java Virtual Machine does not require n to be even. In intuitive terms, values of types long
and double
need not be 64-bit aligned in the local variables array. Implementors are free to decide the appropriate way to represent such values using the two local variables reserved for the value.
The Java Virtual Machine uses local variables to pass parameters on method invocation. On class method invocation, any parameters are passed in consecutive local variables starting from local variable 0. On instance method invocation, local variable 0 is always used to pass a reference to the object on which the instance method is being invoked (this
in the Java programming language). Any parameters are subsequently passed in consecutive local variables starting from local variable 1.
The Java Virtual Machine does not mandate any particular internal structure for objects class instances or arrays.
The Java Virtual Machine does not mandate whether direct value class instances are stored in the Java Virtual Machine stack (2.5.2) or dynamically allocated in the heap (2.5.3).
In some of Oracle's implementations of the Java Virtual Machine, a reference to a class instance is a pointer to a handle that is itself a pair of pointers: one to a table containing the methods of the object and a pointer to the
Class
object that represents the type of the object, and the other to the memory allocated from the heap for the object data.
Most of the instructions in the Java Virtual Machine instruction set encode type information about the operations they perform. For instance, the iload
instruction (iload
) loads the contents of a local variable, which must be an int
, onto the operand stack. The fload
instruction (fload
) does the same with a float
value. The two instructions may have identical implementations, but have distinct opcodes.
For the majority of typed instructions, the instruction type is represented explicitly in the opcode mnemonic by a letter: i
for an int
operation, l
for long
, s
for short
, b
for byte
, c
for char
, f
for float
, and d
for double
and . Instructions prefixed with a
for reference
a
operate on references, and instructions prefixed with v
operate on direct value class instances; where necessary, the specific reference type or direct value class type expected is given as an argument to the instruction. Some instructions for which the type is unambiguous do not have a type letter in their mnemonic. For instance, arraylength
always operates on an object that is an array. Some instructions, such as goto
, an unconditional control transfer, do not operate on typed operands.
Given the Java Virtual Machine's one-byte opcode size, encoding types into opcodes places pressure on the design of its instruction set. If each typed instruction supported all of the Java Virtual Machine's run-time data types, there would be more instructions than could be represented in a byte. Instead, the instruction set of the Java Virtual Machine provides a reduced level of type support for certain operations. In other words, the instruction set is intentionally not orthogonal. Separate instructions can be used to convert between unsupported and supported data types as necessary.
Table 2.11.1-A summarizes the type support in the instruction set of the Java Virtual Machine. A specific instruction, with type information, is built by replacing the T in the instruction template in the opcode column by the letter in the type column. If the type column for some instruction template and type is blank, then no instruction exists supporting that type of operation. For instance, there is a load instruction for type int
, iload
, but there is no load instruction for type byte
.
Note that most instructions in Table 2.11.1-A do not have forms for the integral types byte
, char
, and short
. None have forms for the boolean
type. A compiler encodes loads of literal values of types Whenever values of types byte
and short
using Java Virtual Machine instructions that sign-extend those values to values of type int
at compile-time or run-time. Loads of literal values of types boolean
and char
are encoded using instructions that zero-extend the literal to a value of type int
at compile-time or run-time. Likewise, loads from arrays of values of type boolean
, byte
, short
, and char
are encoded using Java Virtual Machine instructions that sign-extend or zero- extend the values to values of type int
.byte
and short
are loaded onto the operand stack, they are implicitly converted by sign extension to values of type int
. Similarly, whenever values of types boolean
and char
are loaded onto the operand stack, they are implicitly converted by zero extension to values of type int
. Thus, most operations on values originally of actual types boolean
, byte
, char
, and short
are correctly performed by instructions operating on values of computational type int
.
Table 2.11.1-A. Type support in the Java Virtual Machine instruction set
opcode | byte |
short |
int |
long |
float |
double |
char |
reference | value class |
---|---|---|---|---|---|---|---|---|---|
bipush |
sipush |
||||||||
bipush |
sipush |
iconst |
lconst |
fconst |
dconst |
aconst |
vdefault |
||
Tload | iload |
lload |
fload |
dload |
aload |
vload |
|||
Tstore | istore |
lstore |
fstore |
dstore |
astore |
vstore |
|||
Tinc | iinc |
||||||||
Taload | baload |
saload |
iaload |
laload |
faload |
daload |
caload |
aaload |
vaload |
Tastore | bastore |
sastore |
iastore |
lastore |
fastore |
dastore |
castore |
aastore |
vastore |
Tadd | iadd |
ladd |
fadd |
dadd |
|||||
Tsub | isub |
lsub |
fsub |
dsub |
|||||
Tmul | imul |
lmul |
fmul |
dmul |
|||||
Tdiv | idiv |
ldiv |
fdiv |
ddiv |
|||||
Trem | irem |
lrem |
frem |
drem |
|||||
Tneg | ineg |
lneg |
fneg |
dneg |
|||||
Tshl | ishl |
lshl |
|||||||
Tshr | ishr |
lshr |
|||||||
Tushr | iushr |
lushr |
|||||||
Tand | iand |
land |
|||||||
Tor | ior |
lor |
|||||||
Txor | ixor |
lxor |
|||||||
i2T | i2b |
i2s |
i2l |
i2f |
i2d |
||||
l2T | l2i |
l2f |
l2d |
||||||
f2T | f2i |
f2l |
f2d |
||||||
d2T | d2i |
d2l |
d2f |
||||||
a2T | vunbox |
||||||||
v2T | vbox |
||||||||
Tcmp | lcmp |
||||||||
Tcmpl | fcmpl |
dcmpl |
|||||||
Tcmpg | fcmpg |
dcmpg |
|||||||
if_TcmpOP | if_icmpOP |
if_acmpOP |
|||||||
Treturn | ireturn |
lreturn |
freturn |
dreturn |
areturn |
vreturn |
The mapping between Java Virtual Machine actual heap types and Java Virtual Machine computational stack types is summarized by Table 2.11.1-B.
Certain Java Virtual Machine instructions such as pop
and swap
operate on the operand stack without regard to type; however, such instructions are constrained to use only on values of certain categories of computational types, also given in Table 2.11.1-B.
Table 2.11.1-B. Actual and Computational Heap and stack types in the Java Virtual Machine
Category | ||
---|---|---|
boolean |
int |
1 |
byte |
int |
1 |
char |
int |
1 |
short |
int |
1 |
int |
int |
1 |
float |
float |
1 |
reference |
reference |
1 |
value class T | value class T | 1 |
long |
long |
2 |
double |
double |
2 |
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>
, vload
.
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>
, vstore
.
Load a constant on to the operand stack: bipush
, sipush
, ldc
, ldc_w
, ldc2_w
, aconst_null
, vdefault
, 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.
...
The type conversion instructions allow conversion between Java Virtual Machine numeric types. These may be used to implement explicit conversions in user code or to mitigate the lack of orthogonality in the instruction set of the Java Virtual Machine.
The Java Virtual Machine directly supports the following widening numeric conversions:
int
to long
, float
, or double
long
to float
or double
float
to double
The widening numeric conversion instructions are i2l
, i2f
, i2d
, l2f
, l2d
, and f2d
. The mnemonics for these opcodes are straightforward given the naming conventions for typed instructions and the punning use of 2 to mean "to." For instance, the i2d
instruction converts an int
value to a double
.
...
The Java Virtual Machine also directly supports the following narrowing numeric conversions:
int
to byte
, short
, or char
long
to int
float
to int
or long
double
to int
, long
, or float
The narrowing numeric conversion instructions are i2b
, i2c
, i2s
, l2i
, f2i
, f2l
, d2i
, d2l
, and d2f
. A narrowing numeric conversion can result in a value of different sign, a different order of magnitude, or both; it may thereby lose precision.
...
The Java Virtual Machine also supports conversion between reference class instances and direct value class instances.
If a value class V is derived from a value-capable class C, a direct value class instance of V may be converted to a reference to an instance of C with the vbox
instruction. A reference to an instance of C may be converted to a direct value class instance of V with the vunbox
instruction.
Although both class instances and arrays are objects, the Java Virtual Machine creates and manipulates class instances and arrays using distinct sets of instructions:
Reference-typed class instances are created and manipulated with the following instructions:
Create a new reference-typed class instance: new
.
Reference-typed class instances are also created by the
ldc
(2.11.2) andvbox
(2.11.4) instructions.
Access fields of a reference-typed class instance: getfield
, putfield
Dynamically check the type of a reference-typed class instance: instanceof
, checkcast
.
Reference-typed class instances can also be used to invoke instance methods (
invokevirtual
,invokeinterface
,invokespecial
: 2.11.8), throw exceptions (athrow
: 2.11.9), and perform locking (monitorenter
,monitorexit
: 2.11.10).
Direct value class instances are created and manipulated with the following instructions:
Derive a direct value class instance from another value of the same type: vwithfield
.
Direct value class instances are also produced by the
vdefault
(2.11.2) andvunbox
(2.11.4) instructions.
Access fields of a direct value class instance: getfield
.
Arrays are created and manipulated with the following instructions:
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
, vaload
.
Store a value from the operand stack as an array component: bastore
, castore
, sastore
, iastore
, lastore
, fastore
, dastore
, aastore
, vastore
.
Get the length of an array: arraylength
.
Check properties of class instances or arrays: instanceof
, checkcast
.
Dynamically check the type of an array: instanceof
, checkcast
.
Classes and interface also have static
fields, available without operating on a specific class instance. These fields are accessed with getstatic
and putstatic
.
The
static
methods of a class or interface are invoked withinvokestatic
andinvokedynamic
(2.11.8).
The following five instructions invoke methods:
invokevirtual
invokes an instance method of an object, dispatching on the (virtual) type of the object. This is the normal method dispatch in the Java programming language.
invokeinterface
invokes an interface method, searching the methods implemented by the particular run-time object to find the appropriate method.
invokespecial
invokes an instance method requiring special handling, whether an instance initialization method (2.9), a private
method, or a superclass method.
invokestatic
invokes a class (static
) method in a named class.
invokedynamic
invokes the method which is the target of the call site object bound to the invokedynamic
instruction. The call site object was bound to a specific lexical occurrence of the invokedynamic
instruction by the Java Virtual Machine as a result of running a bootstrap method before the first execution of the instruction. Therefore, each occurrence of an invokedynamic
instruction has a unique linkage state, unlike the other instructions which invoke methods.
The method return instructions, which are distinguished by return type, are ireturn
(used to return values of type , boolean
, byte
, char
, short
, or int
)lreturn
, freturn
, dreturn
, and areturn
, and vreturn
. In addition, the return
instruction is used to return from methods declared to be void, instance initialization methods, and class or interface initialization methods.
ClassFile
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:
magic
The magic
item supplies the magic number identifying the class
file format; it has the value 0xCAFEBABE
.
minor_version
, major_version
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. Thus, class file format versions may be ordered lexicographically, for example, 1.5 < 2.0 < 2.1.
A Java Virtual Machine implementation can support a class
file format of version v if and only if v lies in some contiguous range Mi.0 ≤ v ≤ Mj.m. The release level of the Java SE platform to which a Java Virtual Machine implementation conforms is responsible for determining the range.
A Java Virtual Machine implementation determines which version numbers it can support.
Oracle's Java Virtual Machine implementation in JDK release 1.0.2 supports class file format versions 45.0 through 45.3 inclusive. JDK releases 1.1.* support class file format versions in the range 45.0 through 45.65535 inclusive. For k ≥ 2, JDK release 1.k supports class file format versions in the range 45.0 through 44+k.0 inclusive.
Oracle's Java Virtual Machine implementations have supported class file versions according to the following chart:
JDK Release Supported Class File Versions 1.0.2 45.0-45.3 1.1 45.0-45.65535 1.2 45.0-46.0 1.3 45.0-47.0 1.4 45.0-48.0 5 45.0-49.0 6 45.0-50.0 7 45.0-51.0 8 45.0-52.0 9 45.0-53.0 10 {45-54}.0, 54.1 Version 54.1 class files are intended to be supported only by implementations of Java SE 10.
We intend for JVMs to no longer support a contiguous range of version numbers, but rather to support 45.0, 46.0, ..., M.0, along with a designated set of M.n version numbers. (It may also be necessary to support some other historical minor versions, such as instances of 45.m where m ≠ 0?)
It's not yet clear what the relationship is between specifications and the choice to support specific version numbers.
constant_pool_count
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.
constant_pool[]
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.
access_flags
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-A.
Table 4.1-A. 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_VALUE |
0x0100 | Is a value 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. |
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
, and ACC_ENUM
flags set must not be set.
If the ACC_INTERFACE
flag is not set, any of the other flags in Table 4.1-A may be set except ACC_ANNOTATION
. However, such a class file must not have both its ACC_FINAL
and ACC_ABSTRACT
flags set (JLS 8.1.1.2).
A value class is distinguished by the ACC_VALUE
flag. The ACC_VALUE
flag should only be set in classes derived from value-capable classes (4.7.25). In any other class file whose version number is 54.1, the flag must not be set. In any class file whose version number is not 54.1, the flag should not be set and is treated as if it were not set.
The ACC_SUPER
flag indicates which of two alternative semantics is to be expressed by the invokespecial
instruction (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. In JDK releases prior to 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 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.
All bits of the access_flags
item not assigned in Table 4.1-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.
this_class
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 type of the class or interface defined by this class file.
super_class
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 type 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.
For an interface, 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 reference class type Object
.
interfaces_count
The value of the interfaces_count
item gives the number of direct superinterfaces superinterface types of this class or interface type.
interfaces[]
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 type that is a direct superinterface type of this class or interface type, in the left-to-right order given in the source for the type class or interface.
...
A field descriptor represents the type of a class, instance, or local variable.
FieldDescriptor:
FieldType
FieldType:
BaseType
ObjectTypeReferenceClassType DirectValueClassType ArrayType
BaseType:
(one of)
B
C
D
F
I
J
S
Z
ReferenceClassType:
L
ClassName;
DirectValueClassType:
Q
ClassName;
ArrayType:
[
ComponentTypeFieldType
ComponentType:
FieldType
The characters of BaseType, the The terminal symbols in these productions are all ASCII characters.L
and ;
of ObjectType, and the [
of ArrayType
ClassName represents a binary class or interface name encoded in internal form (4.2.1).
The interpretation of field descriptors as types is shown in Table 4.3-A. See 2.2, 2.3, and 2.4 for 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 |
integer |
|
J |
long |
|
L ClassName ; |
reference |
|
Q ClassName ; |
Named direct value class type | |
S |
short |
|
Z |
boolean |
true or false |
[ FieldType |
reference |
The field descriptor of an instance variable of type
int
is simplyI
.
The field descriptor of an instance variable of type
Object
isLjava/lang/Object;
. Note that the internal form of the binary name for classObject
is used.
The field descriptor of an instance variable of the multidimensional array type
double[][][]
is[[[D
.
The "Interpretation" column of Table 4.3-A is redundant; these details are better left to sections 2.2, 2.3, and 2.4.
CONSTANT_Class_info
StructureThe CONSTANT_Class_info
structure is used to represent a class or an interface type (2.2):
The CONSTANT_Class_info
structure historically represents classes or interfaces, with a special accomodation for array types. The attribute is closely related to java.lang.Class
, which is designed to describe all JVM types, including primitive types and array types. Rather than treat these cases as anamolies, we choose to embrace it: a CONSTANT_Class_info
, in general, can represent any type (with a current exception for primitive types). Other parts of the JVM that make use of the structure are responsible for describing, if necessary, the subset of types that are allowed in that context (see, e.g., 4.4.2 and 4.9.1).
Java Virtual Machines may also have distinct internal representations of true classes and interfaces, which correspond to ClassFile
structures.
CONSTANT_Class_info {
u1 tag;
u2 name_index;
}
The items of the CONSTANT_Class_info
structure are as follows:
tag
The tag
item has the value CONSTANT_Class
(7).
name_index
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 of one of the following forms:
If the class
file version number is not 54.1, then the CONSTANT_Utf8_info
structure must not represent a direct value class type or an array type with a direct value class type as its element type.
Because arrays are objects, the opcodes anewarray
and multianewarray
—but not the opcode new
—can reference array "classes" via CONSTANT_Class_info
structures in the constant_pool
table. For such array classes, the name of the class is the descriptor of the array type (4.3.2).
For example, the class name representing the two-dimensional array typeint[][]
is[[I
, while the class name representing the typeThread[]
is[Ljava/lang/Thread;
.
Examples:
- The representation of reference class type
Thread
isjava/lang/Thread
.- The representation of direct value class type
foo.bar.Record
is;Qfoo/bar/Record;
.- The representation of array type
Thread[]
is[Ljava/lang/Thread;
.- The representation of array type
int[][]
is[[I
.
An array type descriptor is valid only if it represents 255 or fewer dimensions.
This assertion is already made in 4.3.2.
The
CONSTANT_Class_info
structure cannot currently express primitive types. For most uses ofCONSTANT_Class_info
, this is not a concern because they would consider it an error for a primitive type to appear. Where primitive types are appropriate, there are various workarounds:
The
newarray
instruction encodes primitive types with a one-byte code.Static fields like
Integer.TYPE
andDouble.TYPE
provide access to the reflectiveClass
objects representing these 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:
tag
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).
class_index
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 type that has the field or method as a member.
The class_index
item of a CONSTANT_Methodref_info
structure must be a reference class type, not an interface type or a direct value class type.
The class_index
item of a CONSTANT_InterfaceMethodref_info
structure must be an interface type.
The class_index
item of a CONSTANT_Fieldref_info
structure may be either a reference class type or an interface type. In a class
file whose version number is 54.1, the class_index
item may also be a direct value class type.
name_and_type_index
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
, the indicated descriptor must be a field descriptor (4.3.2). Otherwise, the indicated descriptor must be a method descriptor (4.3.3). If the name of the method of a CONSTANT_Methodref_info
structure begins with a '<'
('\u003c'
), then the name must be the special name <init>
, representing an instance initialization method (2.9). The return type of such a method must be void
.
CONSTANT_NameAndType_info
StructureThe CONSTANT_NameAndType_info
structure is used to represent a field or method, without indicating which class or interface type 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:
tag
The tag
item of the CONSTANT_NameAndType_info
structure has the value CONSTANT_NameAndType
(12).
name_index
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 the special method name <init>
(2.9) or a valid unqualified name denoting a field or method (4.2.2).
descriptor_index
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).
If the class
file version number is not 54.1 then the CONSTANT_Utf8_info
structure must not mention a direct value class type as a field descriptor, parameter descriptor, return descriptor, or element type of an array type.
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:
tag
The tag
item of the CONSTANT_MethodType_info
structure has the value CONSTANT_MethodType
(16).
descriptor_index
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).
If the class
file version number is not 54.1 then the method descriptor must not mention a direct value class type as a parameter descriptor, return descriptor, or element type of an array type.
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:
access_flags
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.
...
name_index
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).
descriptor_index
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).
The field descriptor must not represent a direct value class type.
If the class
file version number is not 54.1, then the field descriptor must not mention a direct value class type as an element type of an array type.
Fields in version 54.1 class files are not allowed to hold direct value class instances. They are allowed to hold arrays of direct value class instances.
The intent is to support direct value class-typed fields in a future release.
attributes_count
The value of the attributes_count
item indicates the number of additional attributes of this field.
attributes[]
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) and the class or interface initialization method (2.9), 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:
access_flags
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.
...
name_index
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 one of the special method names <init>
or <clinit>
(2.9), or a valid unqualified name denoting a method (4.2.2).
descriptor_index
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 method descriptor (4.3.3).
If the class
file version number is not 54.1, or if the access_flags
of the method has set ACC_NATIVE
, then the method descriptor must not mention a direct value class type as a parameter descriptor, return descriptor, or element type of an array type.
attributes_count
The value of the attributes_count
item indicates the number of additional attributes of this method.
attributes[]
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.
Attributes are used in the ClassFile
, field_info
, method_info
, and Code_attribute
structures of the class
file format (4.1, 4.5, 4.6, 4.7.3).
All attributes have the following general format:
attribute_info {
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];
}
For all attributes, the attribute_name_index
must be a valid unsigned 16-bit index into the constant pool of the class. The constant_pool
entry at attribute_name_index
must be a CONSTANT_Utf8_info
structure (4.4.7) representing the name of the attribute. The value of the attribute_length
item indicates the length of the subsequent information in bytes. The length does not include the initial six bytes that contain the attribute_name_index
and attribute_length
items.
23 24 attributes are predefined by this specification. They are listed three times, for ease of navigation:
Table 4.7-A is ordered by the attributes' section numbers in this chapter. Each attribute is accompanied by the first version of the class
file format in which it was defined, and the corresponding version of the Java SE platform. (For old class
file versions, the JDK release is used instead of the Java SE platform version).
Table 4.7-B is ordered by the first version of the class
file format in which each attribute was defined.
Table 4.7-C is ordered by the location in a class
file where each attribute is defined to appear.
Within the context of their use in this specification, that is, in the attributes
tables of the class
file structures in which they appear, the names of these predefined attributes are reserved.
Any conditions on the presence of a predefined attribute in an attributes
table are specified explicitly in the section which describes the attribute. If no conditions are specified, then the attribute may appear any number of times in an attributes
table.
The predefined attributes are categorized into three groups according to their purpose:
Five Six attributes are critical to correct interpretation of the class
file by the Java Virtual Machine:
ConstantValue
Code
StackMapTable
Exceptions
BootstrapMethods
ValueCapableClass
In a class
file of version V, each of these attributes must be recognized and correctly read by an implementation of the Java Virtual Machine if the implementation recognizes class
files of version V, and V is at least the version where the attribute was first defined, and the attribute appears in a location where it is defined to appear.
Twelve attributes are critical to correct interpretation of the class
file by the class libraries of the Java SE platform:
Exceptions
InnerClasses
EnclosingMethod
Synthetic
Signature
RuntimeVisibleAnnotations
RuntimeInvisibleAnnotations
RuntimeVisibleParameterAnnotations
RuntimeInvisibleParameterAnnotations
RuntimeVisibleTypeAnnotations
RuntimeInvisibleTypeAnnotations
AnnotationDefault
MethodParameters
Each of these attributes in a class
file of version V must be recognized and correctly read by an implementation of the class libraries of the Java SE platform if the implementation recognizes class files of version V, and V is at least the version where the attribute was first defined, and the attribute appears in a location where it is defined to appear.
Six attributes are not critical to correct interpretation of the class
file by either the Java Virtual Machine or the class libraries of the Java SE platform, but are useful for tools:
SourceFile
SourceDebugExtension
LineNumberTable
LocalVariableTable
LocalVariableTypeTable
Deprecated
Use of these attributes by an implementation of the Java Virtual Machine or the class libraries of the Java SE platform is optional. An implementation may use the information that these attributes contain, or otherwise must silently ignore these attributes.
Table 4.7-A. Predefined class
file attributes (by section)
Attribute | Section | class file |
Java SE |
---|---|---|---|
ConstantValue |
4.7.2 | 45.3 | 1.0.2 |
Code |
4.7.3 | 45.3 | 1.0.2 |
StackMapTable |
4.7.4 | 50.0 | 6 |
Exceptions |
4.7.5 | 45.3 | 1.0.2 |
InnerClasses |
[4.7.6] | 45.3 | 1.1 |
EnclosingMethod |
[4.7.7] | 49.0 | 5.0 |
Synthetic |
[4.7.8] | 45.3 | 1.1 |
Signature |
[4.7.9] | 49.0 | 5.0 |
SourceFile |
[4.7.10] | 45.3 | 1.0.2 |
SourceDebugExtension |
[4.7.11] | 49.0 | 5.0 |
LineNumberTable |
[4.7.12] | 45.3 | 1.0.2 |
LocalVariableTable |
[4.7.13] | 45.3 | 1.0.2 |
LocalVariableTypeTable |
[4.7.14] | 49.0 | 5.0 |
Deprecated |
[4.7.15] | 45.3 | 1.1 |
RuntimeVisibleAnnotations |
[4.7.16] | 49.0 | 5.0 |
RuntimeInvisibleAnnotations |
[4.7.17] | 49.0 | 5.0 |
RuntimeVisibleParameterAnnotations |
[4.7.18] | 49.0 | 5.0 |
RuntimeInvisibleParameterAnnotations |
[4.7.19] | 49.0 | 5.0 |
RuntimeVisibleTypeAnnotations |
[4.7.20] | 52.0 | 8 |
RuntimeInvisibleTypeAnnotations |
[4.7.21] | 52.0 | 8 |
AnnotationDefault |
[4.7.22] | 49.0 | 5.0 |
BootstrapMethods |
[4.7.23] | 51.0 | 7 |
MethodParameters |
[4.7.24] | 52.0 | 8 |
ValueCapableClass |
4.7.25 | 54.0 | 10 |
Table 4.7-B. Predefined class
file attributes (by class
file version)
Attribute | class file |
Java SE | Section |
---|---|---|---|
ConstantValue |
45.3 | 1.0.2 | 4.7.2 |
Code |
45.3 | 1.0.2 | 4.7.3 |
Exceptions |
45.3 | 1.0.2 | 4.7.5 |
SourceFile |
45.3 | 1.0.2 | [4.7.10] |
LineNumberTable |
45.3 | 1.0.2 | [4.7.12] |
LocalVariableTable |
45.3 | 1.0.2 | [4.7.13] |
InnerClasses |
45.3 | 1.1 | [4.7.6] |
Synthetic |
45.3 | 1.1 | [4.7.8] |
Deprecated |
45.3 | 1.1 | [4.7.15] |
EnclosingMethod |
49.0 | 5.0 | [4.7.7] |
Signature |
49.0 | 5.0 | [4.7.9] |
SourceDebugExtension |
49.0 | 5.0 | [4.7.11] |
LocalVariableTypeTable |
49.0 | 5.0 | [4.7.14] |
RuntimeVisibleAnnotations |
49.0 | 5.0 | [4.7.16] |
RuntimeInvisibleAnnotations |
49.0 | 5.0 | [4.7.17] |
RuntimeVisibleParameterAnnotations |
49.0 | 5.0 | [4.7.18] |
RuntimeInvisibleParameterAnnotations |
49.0 | 5.0 | [4.7.19] |
AnnotationDefault |
49.0 | 5.0 | [4.7.22] |
StackMapTable |
50.0 | 6 | 4.7.4 |
BootstrapMethods |
51.0 | 7 | [4.7.23] |
RuntimeVisibleTypeAnnotations |
52.0 | 8 | [4.7.20] |
RuntimeInvisibleTypeAnnotations |
52.0 | 8 | [4.7.21] |
MethodParameters |
52.0 | 8 | [4.7.24] |
ValueCapableClass |
54.0 | 10 | 4.7.25 |
Table 4.7-C. Predefined class
file attributes (by location)
Attribute | Location | class file |
---|---|---|
SourceFile |
ClassFile |
45.3 |
InnerClasses |
ClassFile |
45.3 |
EnclosingMethod |
ClassFile |
49.0 |
SourceDebugExtension |
ClassFile |
49.0 |
BootstrapMethods |
ClassFile |
51.0 |
ValueCapableClass |
ClassFile |
54.0 |
ConstantValue |
field_info |
45.3 |
Code |
method_info |
45.3 |
Exceptions |
method_info |
45.3 |
RuntimeVisibleParameterAnnotations , RuntimeInvisibleParameterAnnotations |
method_info |
49.0 |
AnnotationDefault |
method_info |
49.0 |
MethodParameters |
method_info |
52.0 |
Synthetic |
ClassFile , field_info , method_info |
45.3 |
Deprecated |
ClassFile , field_info , method_info |
45.3 |
Signature |
ClassFile , field_info , method_info |
49.0 |
RuntimeVisibleAnnotations , RuntimeInvisibleAnnotations |
ClassFile , field_info , method_info |
49.0 |
LineNumberTable |
Code |
45.3 |
LocalVariableTable |
Code |
45.3 |
LocalVariableTypeTable |
Code |
49.0 |
StackMapTable |
Code |
50.0 |
RuntimeVisibleTypeAnnotations , RuntimeInvisibleTypeAnnotations |
ClassFile , field_info , method_info , Code |
52.0 |
Code
Attribute...
catch_type
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 reference class type of exceptions that this exception handler is designated to catch. The exception handler will be called only if the thrown exception is a reference to an instance of the given class or one of its subclasses.
The verifier checks that the reference class type is
Throwable
or asubclasssubtype 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]).
...
StackMapTable
Attribute...
The Object_variable_info
item indicates that the location has the verification type which is the class type represented by the CONSTANT_Class_info
structure (4.4.1) found in the constant_pool
table at the index given by cpool_index
.
Object_variable_info {
u1 tag = ITEM_Object; /* 7 */
u2 cpool_index;
}
...
Exceptions
Attribute...
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 reference class type that this method is declared to throw.
...
ValueCapableClass
AttributeThe ValueCapableClass
attribute is an optional fixed-length attribute in the attributes table of a ClassFile
structure (4.1). A class marked with a ValueCapableClass
attribute allows the Java Virtual Machine to derive a value class (2.2) from the class.
This implies that the flags
ACC_INTERFACE
andACC_ABSTRACT
should not be set.
A version 54.0 class file can declare a value-capable class. However, loading of a derived value class (5.3) is only performed by a Java Virtual Machine implementation that supports version 54.1 class files. Other JVM implementations will ignore the attribute.
The ValueCapableClass
attribute has the following format:
ValueCapableClass_attribute {
u2 attribute_name_index;
u4 attribute_length;
}
The items of the ValueCapableClass_attribute
structure are as follows:
attribute_name_index
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 "ValueCapableClass"
.
attribute_length
The value of the attribute_length
item must be zero.
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 the jsr_w
opcode may appear in the code
array.
Unless the class
file version number is 54.1, none of the following opcodes may appear in the code
array: vaload
, vastore
, vbox
, vdefault
, vload
, vreturn
, vstore
, vunbox
, vwithfield
; this restriction includes appearances of vload
and vstore
as operands to the wide
opcode.
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 operand of each ldc
instruction and each ldc_w
instruction must be a valid index into the constant_pool
table. The constant pool entry referenced by that index must be of type:
CONSTANT_Integer
, CONSTANT_Float
, or CONSTANT_String
if the class file version number is less than 49.0.CONSTANT_Integer
, CONSTANT_Float
, CONSTANT_String
, or CONSTANT_Class
if the class file version number is 49.0 or 50.0.CONSTANT_Integer
, CONSTANT_Float
, CONSTANT_String
, CONSTANT_Class
, CONSTANT_MethodType
, or CONSTANT_MethodHandle
if the class file version number is 51.0 or above.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 of type CONSTANT_Long
or CONSTANT_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
, getstatic
, and putstatic
, and vwithfield
instruction must represent a valid index into the constant_pool
table. The constant pool entry referenced by that index must be of type CONSTANT_Fieldref
.
The CONSTANT_Class
referenced by the class_index
of the CONSTANT_Fieldref
of a vwithfield
instruction must represent a direct value class type.
The CONSTANT_Class
referenced by the class_index
of the CONSTANT_Fieldref
of a putfield
, getstatic
, or putstatic
instruction must not represent a direct value class type.
The indexbyte operands of each invokevirtual
instruction must represent a valid index into the constant_pool
table. The constant pool entry referenced by that index must be of type CONSTANT_Methodref
.
The indexbyte operands of each invokespecial
and invokestatic
instruction must represent a valid index into the constant_pool
table. If the class file version number is less than 52.0, the constant pool entry referenced by that index must be of type CONSTANT_Methodref
; if the class file version number is 52.0 or above, the constant pool entry referenced by that index must be of type CONSTANT_Methodref
or CONSTANT_InterfaceMethodref
.
The indexbyte operands of each invokeinterface
instruction must represent a valid index into the constant_pool
table. The constant pool entry referenced by that index must be of type CONSTANT_InterfaceMethodref
.
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 type CONSTANT_InvokeDynamic
.
The third and fourth operand bytes of each invokedynamic
instruction must have the value zero.
Only the invokespecial
instruction is allowed to invoke an instance initialization method (2.9).
No other method whose name begins with the character '<'
('\u003c'
) may be called by the method invocation instructions. In particular, the class or interface initialization method specially named <clinit>
is never called explicitly from Java Virtual Machine instructions, but only implicitly by the Java Virtual Machine itself.
The operands of each instanceof
, checkcast
, new
, and anewarray
, vdefault
, vunbox
, vaload
, vastore
, and vbox
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 type CONSTANT_Class
.
The constant pool entry referenced by each instanceof
and checkcast
instruction must represent a reference type.
No The constant pool entry referenced by each new
instruction may reference a constant pool entry of type CONSTANT_Class
that represents an array type (4.3.2).new
instruction must repesent a reference class or interface type. The new
instruction cannot be used to create an array or a direct value class instance.
No anewarray
instruction may be used to create an array of more than 255 dimensions.
The constant pool entry referenced by each vdefault
, vunbox
, vaload
, and vastore
instruction must represent a direct value class type.
The constant pool entry referenced by each vbox
instruction must represent a reference class or interface type.
The constant pool entry referenced the indexbyte operands of each multianewarray
instruction must represent 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
, vload
, istore
, fstore
, astore
, vstore
, 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
, vload
, istore
, fstore
, astore
, vstore
, 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.
An instruction operating on values of type int
is also permitted to operate on values of type boolean
, byte
, char
, and short
.
As noted in 2.3.4 and 2.11.1, the Java Virtual Machine
internallyimplicitly converts values of typesboolean
,byte
,short
, andchar
to typeint
, allowing instructions expecting values of typeint
to operate on them.
...
The type of every class instance that is the target of a method invocation instruction must be assignment compatible with a subtype of the reference class or interface type specified in the instruction (JLS 5.2 4.10.1.2).
The types of the arguments to each method invocation must be method invocation compatible with subtypes of the types given by the method descriptor (JLS 5.3 4.10.1.2, 4.3.3).
Each return instruction must match its method's return type:
boolean
, byte
, char
, short
, or int
, only the ireturn
instruction may be used.float
, long
, or double
, only an freturn
, lreturn
, or dreturn
instruction, respectively, may be used.areturn
instruction may be used, and the type of the returned value must be vreturn
instruction may be used, and the type of the returned value must be the same as the type given by the return descriptor of the method (4.10.1.2).void
must use only the return
instruction.The type of every class instance accessed by a getfield
instruction must be a subtype of the reference class type or direct value class type specified in the instruction (4.10.1.2).
The type of every class instance accessed by a modified by a getfield
instruction orputfield
instruction must be assignment compatible with a subtype of the reference class type specified in the instruction (JLS 5.2 4.10.1.2).
The type of every class instance accessed by a vwithfield
instruction must be the same as the direct value class type specified in the instruction.
putfield
, putstatic
, or vwithfield
instruction must be compatible with the descriptor of the field (4.3.2) of the class instance or class being stored into:
boolean
, byte
, char
, short
, or int
, then the value must be an int
.float
, long
, or double
, then the value must be a float
, long
, or double
, respectively.reference
Note that, due to the restriction on field declarations (4.5), a reference to a field with a direct value class type will later fail to resolve (5.4.3.2).
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.
The component type of the array being stored into by a vastore
, and the type of the value being stored, must be the same as the type specified by the instruction.
The component type of the array being accessed by a vaload
instruction must be the same as the type specified by the instruction.
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 must be the same as or a subclass of the current class.
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 must be the same as or a subclass of the current class.
The type of the operand to each vunbox
instruction must be a reference class or interface type.
The type of the operand to each vbox
instruction must be a direct value class type.
...
...
classIsTypeSafe(Class) :-
classClassName(Class, Name),
classDefiningLoader(Class, L),
superclassChain(Name, L, Chain),
loadedSuperclasses(Class, Supers),
ChainSupers = [],
classSuperClassName(Class, SuperclassName),
classDefiningLoader(Class, L),
loadedClass(SuperclassName, L, Superclass),
classIsNotFinal(Superclass),
classMethods(Class, Methods),
checklist(methodIsTypeSafe(Class), Methods).
classIsTypeSafe(Class) :-
classClassName(Class,
'java/lang/Object'
),
classDefiningLoader(Class, L),
isBootstrapLoader(L),
classMethods(Class, Methods),
checklist(methodIsTypeSafe(Class), Methods).
Changes to 4.10.1.1 and 4.10.1.2, below, use loaded classes rather than verification types to represent the "superclass chain" of a class. This is purely to improve presentation.
...
We stipulate the existence of 30 Prolog predicates ("accessors") that have certain expected behavior but whose formal definitions are not given in this specification.
Extracts the name, ClassName, of the class Class.
True iff the class, Class, is an interface.
True iff the class, Class, is a value class.
True iff the class, Class, is not a final
class.
...
Converts a field descriptor, Descriptor, into the corresponding verification type Type (4.10.1.2).
The verification type derived from types byte
, short
, boolean
, and char
is int
.
Converts a method descriptor, Descriptor, into a list of verification types, ArgTypeList, corresponding to the method argument types, and a verification type, ReturnType, corresponding to the return type.
The verification type derived from types byte
, short
, boolean
, and char
is int
. A void return is represented with the special symbol void
.
Expresses the type given by a CONSTANT_Class_info
as a verification type.
Extracts the instruction stream, ParsedCode, of the method Method in Class, as well as the maximum operand stack size, MaxStack, the maximal number of local variables, FrameSize, the exception handlers, Handlers, and the stack map StackMap.
The representation of the instruction stream and stack map attribute must be as specified in 4.10.1.3 and 4.10.1.4.
True iff the package names of Class1 and Class2 are the same.
True iff the package names of Class1 and Class2 are different.
The above accessors are used to define loadedSuperclasses, which produces a list of a class's superclasses.
loadedSuperclasses(Class, [ Superclass | Rest ]) :-
classSuperClassName(Class, SuperclassName),
classDefiningLoader(Class, L),
loadedClass(SuperclassName, L, Superclass),
loadedSuperclasses(Superclass, Rest).
loadedSuperclasses(Class, []) :-
classClassName(Class,
'java/lang/Object'
),
classDefiningLoader(Class, BL),
isBootstrapLoader(BL).
The loadedSuperclasses predicate replaces superclassChain (4.10.1.2), which had the same effect, but produced a list of class types rather than loaded classes. (Despite the change in representation, all superclasses are loaded in either case.)
Given the introduction of separate reference and direct value class types, it's unnecessarily confusing to continue to use class type structures outside of the scope of their intended application, the representation of types. Instead, the best way to represent a class is with a real loaded class.
When type checking a method's body, it is convenient to access information about the method. For this purpose, we define an environment, a six-tuple consisting of:
void
)We specify accessors to extract information from the environment.
allInstructions(Environment, Instructions) :-
Environment = environment(_Class, Method, ReturnType, Instructions, , ).
exceptionHandlers(Environment, Handlers) :-
_Environment = environment(_Class, _Method, ReturnType, Instructions, , Handlers).
maxOperandStackLength(Environment, MaxStack) :-
_Environment = environment(_Class, _Method, _ReturnType, _Instructions, MaxStack, Handlers).
currentClassLoader(Environment, Loader) :-
Environment = environment(Class, _Method, _ReturnType, _Instructions, _, _),
classDefiningLoader(Class, L).
thisClass(Environment, Class) :-
Environment = environment(Class, _Method, _ReturnType, _Instructions, _, _).
thisClassthisType(Environment,classrefclass(ClassName, L)) :-Environment = environment(Class, _Method, _ReturnType, _Instructions, _, _),
\+ classIsValueClass(Class),
classDefiningLoader(Class, L),
classClassName(Class, ClassName).
thisType(Environment, valclass(ClassName, L)) :-
Environment = environment(Class, _Method, _ReturnType, _Instructions, _, _),
classIsValueClass(Class),
classDefiningLoader(Class, L),
classClassName(Class, ClassName).
thisMethodReturnType(Environment, ReturnType) :-
Environment = environment(_Class, Method, ReturnType, Instructions, , ).
We specify additional predicates to extract higher-level information from the environment.
offsetStackFrame(Environment, Offset, StackFrame) :-
allInstructions(Environment, Instructions), member(stackMap(Offset, StackFrame), Instructions).
currentClassLoader(Environment, Loader) :-
thisClass(Environment, class(_, Loader)).
Finally, we specify a general predicate used throughout the type rules:
notMember(_, []). notMember(X, [A | More]) :- X = A, notMember(X, More).
The principle guiding the determination as to which accessors are stipulated and which are fully specified is that we do not want to over-specify the representation of the
class
file. Providing specific accessors to the Class or Method term would force us to completely specify the format for a Prolog term representing theclass
file.
The type checker enforces a type system based upon a hierarchy of verification types, illustrated below.
Verification type hierarchy:
top
_________/\____________
/ \
/ \
oneWord twoWord
/ | | \ / \
/ | | \ / \
valueClass int float reference long double
| / \
| / \____________
+-----------+ / \
|each direct| / \
|value class| uninitialized Object
|type | / \ \
+-----------+ / \ \
uninitializedThis uninitialized(offset) +------------------+
| reference type |
| hierarchy |
+------------------+
|
|
null
Changes to this chart:
The box "each direct value class type" is added to support direct value class types; a common supertype, valueClass
, is added.
Most verification types have a direct correspondence with the primitive direct value 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
.
Direct value class types correspond to verification types that use the functor valclass. The verification type valclass(N, L) represents the direct value class type of a class with binary name N as loaded by the loader L. Note that L is an initialiting loader (5.3) of the class named N, and may, or may not, be the class's defining loader.
Reference class and interface types correspond to verification types that use the functor class refclass. The verification type class(N, L) refclass(N,L) represents the reference class or interface type of the class or interface whose binary name is N as loaded by the loader L. Note Again, note that L is an initiating loader (5.3) of the class, represented by class(N, L) and may, or may not, be not necessarily the class's defining loader.
For example, the reference class type
Object
would be represented as refclass('java/lang/Object'
,BLL), whereBLthe defining loader of class'java/lang/Object'
, loaded by L, is the bootstrap loader.
Array types correspond to verification types that use the functor arrayOf. The verification type arrayOf(T) represents the array type whose component type is the verification Java Virtual Machine type T.
The Java Virtual Machine types (2.2) that act as array component types are represented as described in this section, with additional atoms denoting primitive types byte
, char
, short
, and boolean
.
For example, the types
int[]
char[]
andObject[]
would be represented byarrayOf(arrayOf(int
)char
) and arrayOf(refclass('java/lang/Object'
, L)), respectively.
The primitive types byte
, char
, short
, and boolean
(field descriptors B
, C
, S
, Z
) have no corresponding verification type, because their values on the operand stack are implicitly converted to type int
. However, arrays of these primitive types do have corresponding verification types.
The verification types uninitializedThis
and uninitialized(Offset)
represent references to objects created with new
that have not yet been initialized ([2.9.2]). The verification type uninitialized(Offset)
is represented by applying the functor uninitialized
to an argument representing the numerical value of the Offset
.
Other verification types are represented in Prolog as atoms whose name denotes the verification type in question.
The subtyping rules for verification types are as follows. Subtyping is reflexive.
isAssignable(X, X).
The verification types which are not reference types in the Java programming language have subtype rules of the form:
isAssignable(v, X) :- isAssignable(the_direct_supertype_of_v, X).
That is, v is a subtype of X if the direct supertype of v is a subtype of X. The rules are:
A type is a subtype of some other type, X, if its direct supertype is a subtype of X.
isAssignable(
oneWord
, top).
isAssignable(twoWord
, top).
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(
valueClass
, X) :- isAssignable(oneWord
, X).
isAssignable(valclass(_, _), X) :- isAssignable(valueClass
, X).
isAssignable(
reference
, X) :- isAssignable(oneWord
, X).
isAssignable(refclass(_, _), X) :- isAssignable(reference
, X).
isAssignable(arrayOf(_), 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 reference types.
isAssignable(
null
, refclass(_, _)).
isAssignable(null
, arrayOf(_)).
isAssignable(null
, X) :- isAssignable(class('java/lang/Object', BL), X), isBootstrapLoader(BL).
isAssignable(null
, X) :- isAssignable(reference
, X).
These subtype rules are not necessarily the most obvious formulation of subtyping. There is a clear split between subtyping rules
for reference types in the Java programming languageamong reference types, and rules for the remaining verification types. The split allows us to state general subtyping relations betweenJava programming languagereference types and other verification types. These relations hold independently of aJavareference 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 theJavasuperclass hierarchy in response to a query of the form refclass(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
in the Java programming language.
Subtype rules for the reference types in the Java programming language are specified recursively with isJavaAssignable isWideningReference.
isAssignable(class(X, Lx), class(Y, Ly)) :-
isJavaAssignable(class(X, Lx), class(Y, Ly)).
isAssignable(arrayOf(X), class(Y, L)) :-
isJavaAssignable(arrayOf(X), class(Y, L)).
isAssignable(arrayOf(X), arrayOf(Y)) :-
isJavaAssignable(arrayOf(X), arrayOf(Y)).
isAssignable(From, To) :- isWideningReference(From, To).
The isWideningReference predicate is only defined for reference types, and will fail to match any non-reference inputs. So it's unnecessary to restrict the form of the inputs to these isAssignable rules in order to avoid testing non-reference types.
For assignments, interfaces are treated like The verifier allows any reference type to be widened to an interface type.Object
.
isWideningReference(refclass(_, _), refclass(To, L)) :-
loadedClass(To, L, ToClass),
classIsInterface(ToClass).
isWideningReference(arrayOf(_), refclass(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 type 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 (
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 reference class type can be widened to another reference class type if that type refers to the loaded class or one of its superclasses.
isJavaAssignable(From, To) :- isJavaSubclassOf(From, To).
isWideningReference(refclass(ClassName, L1), refclass(ClassName, L2)) :-
L1 \= L2,
loadedClass(ClassName, L1, Class),
loadedClass(ClassName, L2, Class).
isWideningReference(refclass(From, L1), refclass(To, L2)) :-
loadedClass(From, L1, FromClass),
loadedClass(To, L2, ToClass),
loadedSuperclasses(FromClass, Supers)
member(ToClass, Supers).
A bug in the previous rules failed to allow the same class to be treated as a subtype of itself when referenced in the context of different initiating class loaders. It's not clear if this has any practical impact (are subtype tests ever performed between types referenced from different classes?), but the first rule above addresses it.
Array types are subtypes of Object
. The intent is also that array types are subtypes of Cloneable
and java.io.Serializable
.
isJavaAssignable(arrayOf(_), class('java/lang/Object'
, BL)) :- isBootstrapLoader(BL).
isJavaAssignable(arrayOf(_), X) :- isArrayInterface(X).
isArrayInterface(class('java/lang/Cloneable', BL)) :- isBootstrapLoader(BL).
isArrayInterface(class('java/io/Serializable', BL)) :- isBootstrapLoader(BL).
isWideningReference(arrayOf(_), refclass(
'java/lang/Object'
, L)) :-loadedClass(
'java/lang/Object'
, L, ObjectClass),
classDefiningLoader(ObjectClass, BL),
isBootstrapLoader(BL).
A bug in the previous rules fails to treat array types as subtypes of class('java/lang/Object'
, L) unless L is the bootstrap loader. Since L is the initiating loader, that rule failed to support the common case of java/lang/Object
being referenced outside of bootstrap classes.
The previous rules also fail to allow an array type to be treated as a subtype of an arbitrary interface type. In practice, it is possible to, say, pass an array as an argument to a method expecting a Runnable
. The earlier rules for interface types address this, making it unnecessary to single out Cloneable
and Serializable
for special treatment.
Subtyping between arrays of primitive type is the identity relation.
isJavaAssignable(arrayOf(X), arrayOf(Y)) :-
atom(X),
atom(Y),
X = Y.
Subtyping between arrays of reference type is covariant.
isWideningReference(arrayOf(X), arrayOf(Y)) :-
compound(X),
compound(Y),
isWideningReference(X, Y).
The subtyping rule for arrays of primitive types is an identity conversion, not a widening; and it is already covered by the reflexive rule for isAssignable.
The subtyping rule for arrays of reference types does not need to check that the inputs are reference types—if not, isWideningReference will not succeed.
Subclassing is reflexive.
isJavaSubclassOf(class(SubclassName, L), class(SubclassName, L)).
isJavaSubclassOf(class(SubclassName, LSub), class(SuperclassName, LSuper)) :-
superclassChain(SubclassName, LSub, Chain),
member(class(SuperclassName, L), Chain),
loadedClass(SuperclassName, L, Sup),
loadedClass(SuperclassName, LSuper, Sup).
This relation is expressed directly with isWideningReference, above. No need to introduce another predicate.
superclassChain(ClassName, L, [class(SuperclassName, Ls) | Rest]) :-
loadedClass(ClassName, L, Class),
classSuperClassName(Class, SuperclassName),
classDefiningLoader(Class, Ls),
superclassChain(SuperclassName, Ls, Rest).
superclassChain('java/lang/Object', L, []) :-
loadedClass('java/lang/Object', L, Class),classDefiningLoader(Class, BL),isBootstrapLoader(BL).
This predicate is moved to 4.10.1.1 and renamed loadedSuperclasses.
...
A few instructions have operands that are constant pool entries representing fields, methods, and dynamic call sites. In the constant pool, a field is represented by a CONSTANT_Fieldref_info
structure, a method is represented by a CONSTANT_InterfaceMethodref_info
structure (for an interface's method) or a CONSTANT_Methodref_info
structure (for a class's method), and a dynamic call site is represented by a CONSTANT_InvokeDynamic_info
structure (4.4.2, 4.4.10). Such structures are represented as functor applications of the form:
field(FieldClassName FieldClassType, FieldName, FieldDescriptor) for a field, where FieldClassType is the name of the class constant pool entry referenced by the class_index
item in the CONSTANT_Fieldref_info
structure, and FieldName and FieldDescriptor correspond to the name and field descriptor referenced by the name_and_type_index
item of the CONSTANT_Fieldref_info
structure.
imethod(MethodIntfName MethodIntfType, MethodName, MethodDescriptor) for an interface's method, where MethodIntfType is the name of the interface constant pool entry referenced by the class_index
item of the CONSTANT_InterfaceMethodref_info
structure, and MethodName and MethodDescriptor correspond to the name and method descriptor referenced by the name_and_type_index
item of the CONSTANT_InterfaceMethodref_info
structure;
method(MethodClassName MethodClassType, MethodName, MethodDescriptor) for a class's method, where MethodClassType is the name of the class constant pool entry referenced by the class_index
item of the CONSTANT_Methodref_info
structure, and MethodName and MethodDescriptor correspond to the name and method descriptor referenced by the name_and_type_index
item of the CONSTANT_Methodref_info
structure; and
dmethod(CallSiteName, MethodDescriptor) for a dynamic call site, where CallSiteName and MethodDescriptor correspond to the name and method descriptor referenced by the name_and_type_index
item of the CONSTANT_InvokeDynamic_info
structure.
For clarity, we assume that field and method descriptors (4.3.2, 4.3.3) are mapped into more readable names: the leading L
and trailing ;
are dropped from class names, and the BaseType characters used for primitive types are mapped to the names of those types.
The descriptor should always be processed with parseFieldDescriptor, so its format doesn't need to be specified.
For example, a
getfield
instruction whose operand was an index into the constant pool that refers to a fieldfoo
of typeF
inclassreference class typeBar
would be represented as getfield(field(classConstant('Bar'
'Bar'
),'foo'
,'F'
)).
...
...
instanceMethodInitialThisType(Class, Method, uninitializedThis) :-
methodName(Method, '<init>'),
classClassName(Class, ClassName),
classDefiningLoader(Class, CurrentLoader),
superclassChain(ClassName, CurrentLoader, Chain),
loadedSuperclasses(Class, Supers),
ChainSupers = [].
...
protected
MembersChanges to the section involve:
CONSTANT_Class_info
and CONSTANT_Fieldref_info
.All instructions that access members must contend with the rules concerning protected
members. This section describes the protected
check that corresponds to JLS 6.6.2.1.
The protected
check applies only to protected
members of superclasses of the current class. protected
members in other classes will be caught by the access checking done at resolution (5.4.4). There are four cases:
If the name of a class is not the name of any superclass, it cannot be a superclass, and so it can safely be ignored.
passesProtectedCheck(Environment, MemberType, MemberName, MemberDescriptor, StackFrame) :-
MemberType \= refclass(_, _).
passesProtectedCheck(Environment,
MemberClassNameMemberType, MemberName, MemberDescriptor, StackFrame) :-MemberType = refclass(MemberClassName, CurrentLoader),
thisClass(Environment,class(CurrentClassName, CurrentLoader)CurrentClass),
superclassChain(CurrentClassName, CurrentLoader, Chain),
notMember(class(MemberClassName, _), Chain).
\+ hasSuperclassWithName(CurrentClass, MemberClassName).
hasSuperclassWithName(Class, SuperclassName) :-
loadedSuperclasses(Class, Supers),
member(Super, Supers),
classClassName(Super, SuperclassName).
If the MemberClassName is the same as the name of a superclass, the class being resolved may indeed be a superclass. In this case, if no superclass named MemberClassName in a different run-time package has a protected
member named MemberName with descriptor MemberDescriptor, the protected
check does not apply.
This is because the actual class being resolved will either be one of these superclasses, in which case we know that it is either in the same run-time package, and the access is legal; or the member in question is not
protected
and the check does not apply; or it will be a subclass, in which case the check would succeed anyway; or it will be some other class in the same run-time package, in which case the access is legal and the check need not take place; or the verifier need not flag this as a problem, since it will be caught anyway because resolution will per force fail.
passesProtectedCheck(Environment,
MemberClassNameMemberType, MemberName, MemberDescriptor, StackFrame) :-MemberType = refclass(MemberClassName, CurrentLoader),
thisClass(Environment,class(CurrentClassName, CurrentLoader)CurrentClass),
superclassChain(CurrentClassName, CurrentLoader, Chain),
member(class(MemberClassName, _), Chain),
hasSuperclassWithName(CurrentClass, MemberClassName),
loadedSuperclasses(CurrentClass, Chain),
classesInOtherPkgWithProtectedMember(
class(CurrentClassName, CurrentLoader)CurrentClass,
MemberName, MemberDescriptor, MemberClassName, Chain, []).
If there does exist a protected
superclass member in a different run-time package, then load MemberClassName; if the member in question is not protected
, the check does not apply. (Using a superclass member that is not protected
is trivially correct.)
passesProtectedCheck(Environment,
MemberClassNameMemberType, MemberName, MemberDescriptor,
frame(_Locals, [Target | Rest], _Flags)) :-MemberType = refclass(MemberClassName, CurrentLoader),
thisClass(Environment,class(CurrentClassName, CurrentLoader)CurrentClass),
superclassChain(CurrentClassName, CurrentLoader, Chain),
member(class(MemberClassName, _), Chain),
hasSuperclassWithName(CurrentClass, MemberClassName),
loadedSuperclasses(CurrentClass, Chain),
classesInOtherPkgWithProtectedMember(
class(CurrentClassName, CurrentLoader)CurrentClass,
MemberName, MemberDescriptor, MemberClassName, Chain, List),
List /= [],
loadedClass(MemberClassName, CurrentLoader, ReferencedClass),
isNotProtected(ReferencedClass, MemberName, MemberDescriptor).
Otherwise, use of a member of an object of type Target requires that Target be assignable to the type of the current class.
passesProtectedCheck(Environment,
MemberClassNameMemberType, MemberName, MemberDescriptor,
frame(_Locals, [Target | Rest], _Flags)) :-MemberType = refclass(MemberClassName, CurrentLoader),
thisClass(Environment,class(CurrentClassName, CurrentLoader)CurrentClass),
superclassChain(CurrentClassName, CurrentLoader, Chain),
member(class(MemberClassName, _), Chain),
hasSuperclassWithName(CurrentClass, MemberClassName),
loadedSuperclasses(CurrentClass, Chain),
classesInOtherPkgWithProtectedMember(
class(CurrentClassName, CurrentLoader)CurrentClass,
MemberName, MemberDescriptor, MemberClassName, Chain, List),
List /= [],
loadedClass(MemberClassName, CurrentLoader, ReferencedClass),
isProtected(ReferencedClass, MemberName, MemberDescriptor),
thisType(Environment, ThisType),
isAssignable(Target,class(CurrentClassName, CurrentLoader)ThisType).
The predicate classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName, Chain, List) is true if List is the set of classes in Chain with name MemberClassName that are in a different run-time package than Class which have a protected
member named MemberName with descriptor MemberDescriptor.
classesInOtherPkgWithProtectedMember(_, _, _, _, [], []).
classesInOtherPkgWithProtectedMember(Class, MemberName,
MemberDescriptor, MemberClassName,
[class(MemberClassName, L)Super | Tail],
[class(MemberClassName, L)Super | T]) :-classClassName(Super, MemberClassName),
differentRuntimePackage(Class,class(MemberClassName, L)Super),
loadedClass(MemberClassName, L, Super),
isProtected(Super, MemberName, MemberDescriptor),
classesInOtherPkgWithProtectedMember(
Class, MemberName, MemberDescriptor, MemberClassName, Tail, T).
classesInOtherPkgWithProtectedMember(Class, MemberName,
MemberDescriptor, MemberClassName,
[class(MemberClassName, L)Super | Tail],
T) :-classClassName(Super, MemberClassName),
differentRuntimePackage(Class,class(MemberClassName, L)Super),
loadedClass(MemberClassName, L, Super),
isNotProtected(Super, MemberName, MemberDescriptor),
classesInOtherPkgWithProtectedMember(
Class, MemberName, MemberDescriptor, MemberClassName, Tail, T).
classesInOtherPkgWithProtectedMember(Class, MemberName,
MemberDescriptor, MemberClassName,
[class(MemberClassName, L)Super | Tail],
T) :-classClassName(Super, MemberClassName),
sameRuntimePackage(Class,class(MemberClassName, L)Super),
classesInOtherPkgWithProtectedMember(
Class, MemberName, MemberDescriptor, MemberClassName, Tail, T).
sameRuntimePackage(Class1, Class2) :-
classDefiningLoader(Class1, L),
classDefiningLoader(Class2, L),
samePackageName(Class1, Class2).
differentRuntimePackage(Class1, Class2) :-
classDefiningLoader(Class1, L1),
classDefiningLoader(Class2, L2),
L1 = L2.
differentRuntimePackage(Class1, Class2) :-
differentPackageName(Class1, Class2).
...
aaload
An aaload
instruction is type safe iff one can validly replace types matching int
and an array type with component type ComponentType where ComponentType is a subtype of Object
, with ComponentType yielding the outgoing type state.
instructionIsTypeSafe(
aaload
, Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-nth1OperandStackIs(2, StackFrame, ArrayType),
arrayComponentType(ArrayType, ComponentType),
isBootstrapLoader(BL),
validTypeTransition(Environment,
[int
, arrayOf(refclass('java/lang/Object'
, BL))],
ComponentType, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
The component type of an array of X is X. We define the component type of null
to be null
.
arrayComponentType(arrayOf(X), X).
arrayComponentType(null
,null
).
aastore
An aastore
instruction is type safe iff one can validly pop types matching Object
, int
, and an array of Object
off the incoming operand stack yielding the outgoing type state.
instructionIsTypeSafe(
aastore
, _Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-isBootstrapLoader(BL),
canPop(StackFrame,
[refclass('java/lang/Object'
, BL),int
, arrayOf(refclass('java/lang/Object'
, BL))],
NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
...
anewarray
An anewarray
instruction with operand CP is type safe iff CP refers to a constant pool entry denoting either a class type or an array type, and one can legally replace a type matching int
on the incoming operand stack with an array with component type given by CP, yielding the outgoing type state.
instructionIsTypeSafe(anewarray(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
(CP = class(_, _) ; CP = arrayOf(_)),
parseConstantClassType(CP, ComponentType),
validTypeTransition(Environment, [int
], arrayOf(CPComponentType), StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
We don't need to assert that CP is a reference class type or array type (or, now, direct value class type). There are no other possibilities, assuming the bytecode is properly formatted (4.8, 4.9.1).
...
athrow
An athrow
instruction is type safe iff the top of the operand stack matches Throwable
.
instructionIsTypeSafe(
athrow
, _Environment, _Offset, StackFrame, afterGoto, ExceptionStackFrame) :-isBootstrapLoader(BL),
canPop(StackFrame, [refclass('java/lang/Throwable'
, BL)], _PoppedStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
...
checkcast
A checkcast
instruction with operand CP is type safe iff CP refers to a constant pool entry denoting either a class or an array, 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) :-
(CP = class(_, _) ; CP = arrayOf(_)),
parseConstantClassType(CP, Type),
isBootstrapLoader(BL),
validTypeTransition(Environment, [refclass('java/lang/Object'
, BL)],CPType, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
We don't need to assert that CP is not a direct value class type. That was already asserted by format checking (4.8, 4.9.1).
...
getfield
A getfield
instruction with operand CP is type safe iff CP refers to a constant pool entry denoting a field whose declared type is FieldType, declared in a class FieldClass type FieldClassType, and one can validly replace a type matching FieldClassType with type FieldType on the incoming operand stack yielding the outgoing type state. FieldClass must not be an array type. protected
fields are subject to additional checks (4.10.1.8).
instructionIsTypeSafe(getfield(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
CP = field(CC, FieldName, FieldDescriptor),
parseConstantClassType(CC, FieldClassType),
parseFieldDescriptor(FieldDescriptor, FieldType),
passesProtectedCheck(Environment,FieldClassFieldClassType, FieldName, FieldDescriptor, StackFrame),
validTypeTransition(Environment, [class(FieldClass)FieldClassType], FieldType, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
...
instanceof
An instanceof instruction with operand CP is type safe iff CP refers to a constant pool entry denoting either a class or an array, 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) :-
(CP = class(_, _) ; CP = arrayOf(_)),
isBootstrapLoader(BL),
validTypeTransition(Environment, [refclass('java/lang/Object'
, BL)],int
, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
We don't need to assert that CP is not a direct value class type. That was already asserted by format checking (4.8, 4.9.1).
...
invokeinterface
An invokeinterface instruction is type safe iff all of the following are true:
<init>
.<clinit>
.instructionIsTypeSafe(invokeinterface(CP, Count, 0), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
CP = imethod(CC, MethodName, Descriptor),
MethodName \='<init>'
,
MethodName \='<clinit>'
,
parseConstantClassType(CC, MethodIntfType),
parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),
currentClassLoader(Environment, CurrentLoader),
reverse([class(MethodIntfName, CurrentLoader)MethodIntfType | OperandArgList], StackArgList),
canPop(StackFrame, StackArgList, TempFrame),
validTypeTransition(Environment, [], ReturnType, TempFrame, NextStackFrame),
countIsValid(Count, StackFrame, TempFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
The Count operand of an invokeinterface
instruction is valid if it equals the size of the arguments to the instruction. This is equal to the difference between the size of InputFrame and OutputFrame.
countIsValid(Count, InputFrame, OutputFrame) :-
_InputFrame = frame(_Locals1, OperandStack1, Flags1),
_OutputFrame = frame(_Locals2, OperandStack2, Flags2),
length(OperandStack1, Length1),
length(OperandStack2, Length2),
Count =:= Length1 - Length2.
invokespecial
An invokespecial
instruction is type safe iff all of the following are true:
Its first operand, CP, refers to a constant pool entry denoting a method named MethodName with descriptor Descriptor that is a member of a class MethodClassName type MethodClassType.
Either:
<init>
.<clinit>
.instructionIsTypeSafe(invokespecial(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
CP = method(CC, MethodName, Descriptor),
MethodName \='<init>'
,
MethodName \='<clinit>'
,
parseConstantClassType(CC, MethodClassType),
parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),
thisType(Environment,class(CurrentClassName, CurrentLoader)ThisType),
reverse([class(CurrentClassName, CurrentLoader)ThisType | OperandArgList], StackArgList),
validTypeTransition(Environment, StackArgList, ReturnType, StackFrame, NextStackFrame),
currentClassLoader(Environment, L),
reverse([class(MethodClassName, CurrentLoader)MethodClassType | OperandArgList], StackArgList2),
validTypeTransition(Environment, StackArgList2, ReturnType, StackFrame, _ResultStackFrame),
isAssignable(class(CurrentClassName, CurrentLoader)ThisType,
class(MethodClassName, CurrentLoader)MethodClassType),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
Or:
MethodName is <init>
.
Descriptor specifies a void
return type.
One can validly pop types matching the argument types given in Descriptor and an uninitialized type, UninitializedArg, off the incoming operand stack, yielding OperandStack.
The outgoing type state is derived from the incoming type state by first replacing the incoming operand stack with OperandStack and then replacing all instances of UninitializedArg with the type of instance being initialized.
instructionIsTypeSafe(invokespecial(CP), Environment, _Offset, StackFrame,
NextStackFrame, ExceptionStackFrame) :-CP = method(CC,
'<init>'
, Descriptor),
parseConstantClassType(CC, MethodClassType),
parseMethodDescriptor(Descriptor, OperandArgList,void
),
reverse(OperandArgList, StackArgList),
canPop(StackFrame, StackArgList, TempFrame),
TempFrame = frame(Locals, FullOperandStack, Flags),
FullOperandStack = [UninitializedArg | OperandStack],
currentClassLoader(Environment, CurrentLoader),
rewrittenUninitializedType(UninitializedArg, Environment,
class(MethodClassName, CurrentLoader)MethodClassType,ThisInitType),
rewrittenInitializationFlags(UninitializedArg, Flags, NextFlags),
substitute(UninitializedArg, InitType, OperandStack, NextOperandStack),
substitute(UninitializedArg, InitType, Locals, NextLocals),
NextStackFrame = frame(NextLocals, NextOperandStack, NextFlags),
ExceptionStackFrame = frame(Locals, [], Flags),
passesProtectedCheck(Environment, MethodClassType,'<init>'
, Descriptor, NextStackFrame).
To compute what type the uninitialized argument's type needs to be rewritten to, there are two cases:
uninitializedThis
. This type will be rewritten to the type of the class of the <init>
method.new
. The uninitialized arg type is rewritten to MethodClass, the type of the method holder of <init>
. We check whether there really is a new
instruction at Address.rewrittenUninitializedType(
uninitializedThis
, Environment, MethodClassType, MethodClassType) :-MethodClassType = refclass(MethodClassName, CurrentLoader),
thisType(Environment, MethodClassType).
rewrittenUninitializedType(
uninitializedThis
, Environment, MethodClassType, MethodClassType) :-MethodClassType = refclass(MethodClassName, CurrentLoader),
thisClass(Environment,class(thisClassName, thisLoader)CurrentClass),
superclassChain(thisClassName, thisLoader, [MethodClass | Rest]).
classSuperClassName(CurrentClass, MethodClassName).
rewrittenUninitializedType(uninitialized(Address), Environment, MethodClassType, MethodClassType) :-
allInstructions(Environment, Instructions),
member(instruction(Address, new(MethodClass)), Instructions).
rewrittenInitializationFlags(uninitializedThis, Flags, []). rewrittenInitializationFlags(uninitialized(), Flags, Flags).
substitute(_Old, _New, [], []).
substitute(Old, New, [Old | FromRest], [New | ToRest]) :-
substitute(Old, New, FromRest, ToRest).
substitute(Old, New, [From1 | FromRest], [From1 | ToRest]) :-
From1 = Old,
substitute(Old, New, FromRest, ToRest).
The rule for invokespecial of an
<init>
method is the sole motivation for passing back a distinct exception stack frame. The concern is that when initializing an object within its constructor,invokespecial
can cause a superclass<init>
method to be invoked, and that invocation could fail, leaving this uninitialized. This situation cannot be created using source code in the Java programming language, but can be created by programming in bytecode directly.
In this situation, the original frame holds an uninitialized object in local variable 0 and has flag
flagThisUninit
. Normal termination ofinvokespecial
initializes the uninitialized object and turns off theflagThisUninit
flag. But if the invocation of an<init>
method throws an exception, the uninitialized object might be left in a partially initialized state, and needs to be made permanently unusable. This is represented by an exception frame containing the broken object (the new value of the local) and theflagThisUninit
flag (the old flag). There is no way to get from an apparently-initialized object bearing theflagThisUninit
flag to a properly initialized object, so the object is permanently unusable.
If not for this situation, the flags of the exception stack frame would always be the same as the flags of the input stack frame.
...
invokevirtual
An invokevirtual
instruction is type safe iff all of the following are true:
<init>
.<clinit>
.protected
, the usage conforms to the special rules governing access to protected members (4.10.1.8).instructionIsTypeSafe(invokevirtual(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
CP = method(CC, MethodName, Descriptor),
MethodName ='<init>'
,
MethodName ='<clinit>'
,
parseConstantClassType(CC, MethodClassType),
parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),
reverse(OperandArgList, ArgList),
currentClassLoader(Environment, CurrentLoader),
reverse([class(MethodClassName, CurrentLoader)MethodClassType | OperandArgList], StackArgList),
validTypeTransition(Environment, StackArgList, ReturnType, StackFrame, NextStackFrame),
canPop(StackFrame, ArgList, PoppedFrame),
passesProtectedCheck(Environment, MethodClassType, MethodName, Descriptor, PoppedFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
...
ldc
, ldc_w
, ldc2_w
An ldc
instruction with operand CP is type safe iff CP refers to a constant pool entry denoting an entity of type Type, where Type is either int
, float
, String
, Class
, java.lang.invoke.MethodType
, or java.lang.invoke.MethodHandle
, and one can validly push Type onto the incoming operand stack yielding the outgoing type state.
instructionIsTypeSafe(ldc(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
functor(CP, Tag, _),
isBootstrapLoader(BL),
member([Tag, Type], [
[int,int
],
[float,float
],
[string, refclass('java/lang/String'
, BL)],
[classConst, refclass('java/lang/Class'
, BL)],
[methodTypeConst, refclass('java/lang/invoke/MethodType'
, BL)],
[methodHandleConst, refclass('java/lang/invoke/MethodHandle'
, BL)],
]),
validTypeTransition(Environment, [], Type, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
An ldc_w
instruction is type safe iff the equivalent ldc instruction is type safe.
instructionHasEquivalentTypeRule(ldc_w(CP), ldc(CP)).
An ldc2_w
instruction with operand CP is type safe iff CP refers to a constant pool entry denoting an entity of type Tag, where Tag is either long
or double
, and one can validly push Tag onto the incoming operand stack yielding the outgoing type state.
instructionIsTypeSafe(ldc2_w(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
functor(CP, Tag, _),
member(Tag, [long, double]),
validTypeTransition(Environment, [], Tag, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
...
multianewarray
A multianewarray instruction with operands CP and Dim is type safe iff CP refers to a constant pool entry denoting an array type whose dimension is greater or equal to Dim, Dim is strictly positive, and one can validly replace Dim int types on the incoming operand stack with the type denoted by CP yielding the outgoing type state.
instructionIsTypeSafe(multianewarray(CP, Dim), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
parseConstantClassType(CP, ArrayType),
CPArrayType = arrayOf(_),
arrayDimensions(CPArrayType, Dimension),
Dimension >= Dim,
Dim > 0,
/* Make a list of Dim ints */
findall(int
, between(1, Dim, _), IntList),
validTypeTransition(Environment, IntList,CPArrayType, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
The dimensions of an array type whose component type is also an array type is one more than the dimensions of its component type.
classDimension(arrayOf(X), Dimension) :-
classDimension(X, Dimension1),
Dimension is Dimension1 + 1.
classDimension(_, Dimension) :-
Dimension = 0.
arrayDimensions(arrayOf(X), XDimensions + 1) :- arrayDimensions(X, XDimensions).
arrayDimensions(Type, 0) :- Type \= arrayOf(_).
Renamed this predicate, since the element type is not necessarily a class type. Also addressed a bug: the second rule previously would match array types as well as non-array types.
new
A new
instruction with operand CP at offset Offset is type safe iff CP refers to a constant pool entry denoting a class type, the type uninitialized(Offset) does not appear in the incoming operand stack, and one can validly push uninitialized(Offset) onto the incoming operand stack and replace uninitialized(Offset) with top
in the incoming local variables yielding the outgoing type state.
instructionIsTypeSafe(new(CP), Environment, Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
StackFrame = frame(Locals, OperandStack, Flags),
CP = class(_, _),
NewItem = uninitialized(Offset),
notMember(NewItem, OperandStack),
substitute(NewItem,top
, Locals, NewLocals),
validTypeTransition(Environment, [], NewItem, frame(NewLocals, OperandStack, Flags), NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
The substitute predicate is defined in the rule for invokespecial
.
We don't need to assert that CP is a reference class or interface type. That was already asserted by format checking (4.8, 4.9.1).
...
putfield
A putfield
instruction with operand CP is type safe iff CP refers to a constant pool entry denoting a field whose declared type is FieldType, declared in a class FieldClass type FieldClassType, and one can validly pop types matching FieldType and FieldClass FieldClassType off the incoming operand stack yielding the outgoing type state.
instructionIsTypeSafe(putfield(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
CP = field(CC, FieldName, FieldDescriptor),
parseConstantClassType(CC, FieldClassType),
parseFieldDescriptor(FieldDescriptor, FieldType),
canPop(StackFrame, [FieldType], PoppedFrame),
passesProtectedCheck(Environment, FieldClassType, FieldName, FieldDescriptor, PoppedFrame),
currentClassLoader(Environment, CurrentLoader),
canPop(StackFrame, [FieldType,class(FieldClass, CurrentLoader)FieldClassType], NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
...
vaload
A vaload
instruction with operand CP is type safe iff CP refers to a type ComponentType and one can validly replace types matching int
and an array of ComponentType on the incoming operand stack with ComponentType, yielding the outgoing type state.
instructionIsTypeSafe(vaload(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
parseConstantClassType(CP, ComponentType),
validTypeTransition(Environment, [int
, arrayOf(ComponentType)], ComponentType, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
vastore
A vastore
instruction with operand CP is type safe iff CP refers to a type ComponentType and one can validly pop types matching ComponentType, int
, and array of ComponentType off the incoming operand stack yielding the outgoing type state.
instructionIsTypeSafe(vastore(CP), _Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
parseConstantClassType(CP, ComponentType),
canPop(StackFrame, [ComponentType,int
, arrayOf(ComponentType)], NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
vbox
A vbox
instruction with operand CP is type safe iff CP refers to a type BoxedType and one can legally replace a type matching valueClass
on the incoming operand stack with BoxedType, yielding the outgoing type state.
instructionIsTypeSafe(vbox(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
parseConstantClassType(CP, BoxedType),
validTypeTransition(Environment, [valueClass
], BoxedType, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
vdefault
A vdefault
instruction with operand CP is type safe iff CP refers to a type DirectValueClassType and one can validly push DirectValueClassType onto the incoming operand stack yielding the outgoing type state.
instructionIsTypeSafe(vdefault(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
parseConstantClassType(CP, DirectValueClassType),
validTypeTransition(Environment, [], DirectValueClassType, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
vload
A vload
instruction with operand Index is type safe and yields an outgoing type state NextStackFrame, if a load instruction with operand Index and type valueClass
is type safe and yields an outgoing type state NextStackFrame.
instructionIsTypeSafe(vload(Index), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
loadIsTypeSafe(Environment, Index,
valueClass
, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
vreturn
A vreturn
instruction is type safe iff the enclosing method has a declared return type, ReturnType, that is a direct value class type, and one can validly pop a type matching ReturnType off the incoming operand stack.
instructionIsTypeSafe(
vreturn
, Environment, _Offset, StackFrame, afterGoto, ExceptionStackFrame) :-thisMethodReturnType(Environment, ReturnType),
isAssignable(ReturnType,valueClass
),
canPop(StackFrame, [ReturnType], _PoppedStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
vstore
A vstore
instruction with operand Index is type safe and yields an outgoing type state NextStackFrame, if a store instruction with operand Index and type valueClass
is type safe and yields an outgoing type state NextStackFrame.
instructionIsTypeSafe(astore(Index), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
storeIsTypeSafe(Environment, Index,
valueClass
, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
vunbox
A vunbox
instruction with operand CP is type safe iff CP refers to a type UnboxedType and one can legally replace a type matching reference
on the incoming operand stack with BoxedType, yielding the outgoing type state.
instructionIsTypeSafe(vunbox(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
parseConstantClassType(CP, UnboxedType),
validTypeTransition(Environment, [reference
], UnboxedType, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
vwithfield
A vwithfield
instruction with operand CP is type safe iff CP refers to a constant pool entry denoting a field whose declared type is FieldType, declared in a direct value class type FieldClassType, and one can validly replace types matching FieldType and FieldClassType on the incoming operand stack with FieldClassType, yielding the outgoing type state.
instructionIsTypeSafe(vwithfield(CP), Environment, _Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :-
CP = field(CC, FieldName, FieldDescriptor),
parseConstantClassType(CC, FieldClassType)
parseFieldDescriptor(FieldDescriptor, FieldType),
validTypeTransition(Environment, [FieldType, FieldClassType], FieldClassType, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).
The Java Virtual Machine maintains a per-type per-class constant pool (2.5.5), a run-time data structure that serves many of the purposes of the symbol table of a conventional programming language implementation.
The constant_pool
table (4.4) in the binary representation of a class or interface is used to construct the run-time constant pool upon class or interface creation (5.3). All references in the run-time constant pool are initially symbolic. The symbolic references in the run-time constant pool are derived from structures in the binary representation of the class or interface as follows:
A symbolic reference to a class or interface type is derived from a CONSTANT_Class_info
structure (4.4.1) in the binary representation of a class or interface. Such a reference gives the name of the class or interface in the form returned by the Class.getName
method, that is:
For an array class of n dimensions, the name begins with n occurrences of the ASCII "["
character followed by a representation of the element type:
Whenever this chapter refers to the name of a class or interface, it should be understood to be in the form returned by the Class.getName
method.
This extended description of the form of the CONSTANT_Class_info
attribute is redundant and better left to section 4.4.1.
A symbolic reference to a field of a class or an interface type is derived from a CONSTANT_Fieldref_info
structure (4.4.2) in the binary representation of a class or interface. Such a reference gives the name and descriptor of the field, as well as a symbolic reference to the class or interface type in which the field is to be found.
A symbolic reference to a method of a class is derived from a CONSTANT_Methodref_info
structure (4.4.2) in the binary representation of a class or interface. Such a reference gives the name and descriptor of the method, as well as a symbolic reference to the class type in which the method is to be found.
A symbolic reference to a method of an interface is derived from a CONSTANT_InterfaceMethodref_info
structure (4.4.2) in the binary representation of a class or interface. Such a reference gives the name and descriptor of the interface method, as well as a symbolic reference to the interface type in which the method is to be found.
...
Creation of a class or interface C denoted by the name N consists of the construction in the method area of the Java Virtual Machine (2.5.4) of an implementation-specific internal representation of C. Class or interface creation is triggered by another class or interface D, which references C through its run-time constant pool. Class or interface creation may also be triggered by D invoking methods in certain Java SE platform class libraries (2.12) such as reflection.
If C is not an array class, it A class or interface C is created by loading a binary representation of C (4) using a class loader. Array classes do not have an external binary representation; they are created by the Java Virtual Machine rather than by a class loader.
There are two kinds of class loaders: the bootstrap class loader supplied by the Java Virtual Machine, and user-defined class loaders. Every user-defined class loader is an instance of a subclass of the abstract class ClassLoader
. Applications employ user-defined class loaders in order to extend the manner in which the Java Virtual Machine dynamically loads and thereby creates classes. User-defined class loaders can be used to create classes that originate from user-defined sources. For example, a class could be downloaded across a network, generated on the fly, or extracted from an encrypted file.
A class loader L may create C by defining it directly or by delegating to another class loader. If L creates C directly, we say that L defines C or, equivalently, that L is the defining loader of C.
When one class loader delegates to another class loader, the loader that initiates the loading is not necessarily the same loader that completes the loading and defines the class. If L creates C, either by defining it directly or by delegation, we say that L initiates loading of C or, equivalently, that L is an initiating loader of C.
At run time, a class or interface is determined not by its name alone, but by a pair: its binary name (4.2.1) and its defining class loader. Each such class or interface belongs to a single run-time package. The run-time package of a class or interface is determined by the package name and defining class loader of the class or interface.
The Java Virtual Machine uses one of three procedures to create class or interface C denoted by N:
If N has the form ClassName$Value
for some name ClassName, a value class is generated by the Java Virtual Machine, as follows:
The name ClassName is used to load a class or interface OriginalClass, as if by resolving a symbolic reference from D to reference class or interface type ClassName (5.4.3.1). If an error occurs, creation of ClassName$Value
fails for the same reason.
Otherwise, if OriginalClass does not have a ValueCapableClass
attribute (4.7.25), creation of ClassName$Value
fails with a NoClassDefFoundError
.
Otherwise, OriginalClass must have all of the following properties, or an IncompatibleClassChangeError
occurs.
ACC_FINAL
(and, thus, neither ACC_INTERFACE
nor ACC_ABSTRACT
).Object
.ACC_FINAL
.Value capable classes are also encouraged to minimize exposure of instances' identity by declaring only private instance initializers; overriding the
toString
,equals
, andhashCode
methods; not overriding theclone
andfinalize
methods; and not delegating to the methods ofObject
.
Otherwise, a ClassFile
structure (4.1) with the following properties is produced:
ACC_VALUE
is set, along with any other flags of OriginalClass.this_class
is the direct value class type ;QClassName$Value;
.super_class
is the reference class type java/lang/Object
.interfaces
.fields
have the same flags, names, and descriptors as the non-static
fields of OriginalClass. They have no attributes. There are no static
fields.methods
.attributes
.The Java Virtual Machine attempts to derive a class denoted by ClassName$Value
from the ClassFile
structure, using the defining loader of OriginalClass and following the algorithm found in 5.3.5. That class is C.
If N denotes a nonarray class or an interface, one of the two following methods is used to load and thereby create C:
If Otherwise, if D was defined by the bootstrap class loader, then the bootstrap class loader initiates loading of C (5.3.1).
If Otherwise D was defined by a user-defined class loader, then and that same user-defined class loader initiates loading of C (5.3.2).
Otherwise N denotes an array class. An array class is created directly by the Java Virtual Machine (5.3.3), not by a class loader. However, the defining class loader of D is used in the process of creating array class C.
References to loading of "array classes" are removed to clarify that types, such as array types, need not be loaded. Only classes and interfaces are loaded.
If an error occurs during class loading, then an instance of a subclass of LinkageError
must be thrown at a point in the program that (directly or indirectly) uses the class or interface being loaded.
...
The following steps are used to load and thereby create the nonarray class or interface C denoted by N using the bootstrap class loader.
...
The following steps are used to load and thereby create the nonarray class or interface C denoted by N using a user-defined class loader L.
...
The following steps are used to create the array class C denoted by N using class loader L. Class loader L may be either the bootstrap class loader or a user-defined class loader.
If L has already been recorded as an initiating loader of an array class with the same component type as N, that class is C, and no array class creation is necessary.
Otherwise, the following steps are performed to create C:
If the component type is a reference type, the algorithm of this section (5.3) is applied recursively using class loader L in order to load and thereby create the component type of C.
The Java Virtual Machine creates a new array class with the indicated component type and number of dimensions.
If the component type is a reference type, C is marked as having been defined by the defining class loader of the component type. Otherwise, C is marked as having been defined by the bootstrap class loader.
In any case, the Java Virtual Machine then records that L is an initiating loader for C (5.3.4).
If the component type is a reference
type, the accessibility of the array class is determined by the accessibility of its component type. Otherwise, the accessibility of the array class is public
.
This section is unnecessary. There is no need for the notion of "loading" to extend to array types and other types.
Ensuring type safe linkage in the presence of class loaders requires special care. It is possible that when two different class loaders initiate loading of a class or interface denoted by N, the name N may denote a different class or interface in each loader.
When a class or interface C = <N₁, L₁> makes a symbolic reference to a field or method of another class or interface D = <N₂, L₂>, the symbolic reference includes a descriptor specifying the type of the field, or the return and argument types of the method. It is essential that any type class or interface name N mentioned in the field or method descriptor denote the same class or interface when loaded by L₁ and when loaded by L₂.
To ensure this, the Java Virtual Machine imposes loading constraints of the form N^L₁ = N^L₂ during preparation (5.4.2) and resolution (5.4.3).
The class or interface names mentioned by a descriptor (4.3) are as follows:
V
, its return descriptor.L
Q
This definition of "mentions" allows us to eliminate boilerplate in a handful of other sections and gives us a single location to define how loading constraints are derived from new kinds of types.
To enforce these loading constraints, the Java Virtual Machine will, at certain prescribed times (see 5.3.1, 5.3.2, 5.3.3, and 5.3.5), record that a particular loader is an initiating loader of a particular class. After recording that a loader is an initiating loader of a class, the Java Virtual Machine must immediately check to see if any loading constraints are violated. If so, the record is retracted, the Java Virtual Machine throws a LinkageError, and the loading operation that caused the recording to take place fails.
class
File RepresentationThe following steps are used to derive a class for the Class
objectnonarray class or interface C denoted by N using loader L from a purported representation in class file format.
...
Preparation involves creating the static fields for a class or interface and initializing such fields to their default values (2.3, 2.4). This does not require the execution of any Java Virtual Machine code; explicit initializers for static fields are executed as part of initialization (5.5), not preparation.
During preparation of a class or interface C, the Java Virtual Machine also imposes loading constraints (5.3.4). Let L₁ be the defining loader of C. For each method m declared in C that overrides (5.4.5) a method declared in a superclass or superinterface <D, L₂>, the Java Virtual Machine imposes the following loading constraints: for each class or interface name N mentioned by the descriptor of m, the Java Virtual Machine imposes the loading constraint N^L₁ = N^L₂.
Given that the return type of m is Tr, and that the formal parameter types of m are Tf1, ..., Tfn, then:
If Tr not an array type, let T0 be Tr; otherwise, let T0 be the element type (2.4) of Tr.
For i = 1 to n: If Tfi is not an array type, let Ti be Tfi; otherwise, let Ti be the element type (2.4) of Tfi.
Then Ti^L₁ =Ti^L₂ for i = 0 to n.
Furthermore, if C implements a method m declared in a superinterface of C, but C does not itself declare the method m, then let <D, L₂> be the superclass of C that declares the implementation of method m inherited by C. The Java Virtual Machine imposes the following constraints: For each class or interface name N mentioned by the descriptor of m, the Java Virtual Machine imposes the loading constraint N^L₂ = N^L₃.
Given that the return type of m is Tr, and that the formal parameter types of m are Tf1, ..., Tfn, then:
If Tr not an array type, let T0 be Tr; otherwise, let T0 be the element type (2.4) of Tr.
For i = 1 to n: If Tfi is not an array type, let Ti be Tfi; otherwise, let Ti be the element type (2.4) of Tfi.
Then Ti^L₂ =Ti^L₃ for i = 0 to n.
Preparation may occur at any time following creation but must be completed prior to initialization.
The Java Virtual Machine instructions anewarray
, checkcast
, getfield
, getstatic
, instanceof
, invokedynamic
, invokeinterface
, invokespecial
, invokestatic
, invokevirtual
, ldc
, ldc_w
, multianewarray
, new
, putfield
, and putstatic
, vaload
, vastore
, vbox
, vdefault
, vunbox
, and vwithfield
make symbolic references to the run-time constant pool. Execution of any of these instructions requires resolution of its symbolic reference.
Resolution is the process of dynamically determining concrete values from symbolic references in the run-time constant pool.
...
A reference to a type (4.4.1) may take the form of a reference class or interface type, a direct value class type, or an array type.
To resolve an unresolved symbolic reference from D to a reference class or interface type T C denoted by with class or interface name N, the following steps are performed:
The defining class loader of D is used to create a class or interface, C, 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 type resolution.
If C is an array class and its element type is a reference type, then a symbolic reference to the class or interface representing the element type is resolved by invoking the algorithm in 5.4.3.1 recursively.
The loaded class must not be a value class. If C has its ACC_VALUE
flag set, type resolution throws an IncompatibleClassChangeError
.
Finally, access Access permissions to C are checked. If C is not accessible 5.4.4 to D, class or interface type resolution throws an IllegalAccessError
.
This condition can occur, for example, if C is a class that was originally declared to be
public
but was changed to be non-public
after D was compiled.
Finally, a representation, T, of the reference class or interface type of C is created.
To resolve an unresolved symbolic reference from D to a direct value class type T with class name N, the following steps are performed:
The defining class loader of D is used to create a class or interface, C, denoted by N. 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 type resolution.
The loaded class must be a value class. If C does not have its ACC_VALUE
flag set, type resolution throws an IncompatibleClassChangeError
.
Access permissions to C are checked. If C is not accessible 5.4.4 to D, type resolution throws an IllegalAccessError
.
Finally, a representation, T, of the direct value class type of C is created.
To resolve an unresolved symbolic reference from D to an array type T, the following steps are performed:
The component type, S, of the array is created by applying the rules of this section recursively.
Any exception that can be thrown as a result of type resolution can occur when creating the component type.
A representation, T, of an array type with component type S is created.
To resolve an unresolved symbolic reference from D to a primitive type, a representation of that type is created.
A
CONSTANT_Class_info
cannot be used to represent a primitive type. However, it is sometimes necessary to resolve a reference to a primitive type expressed as a descriptor (4.3.2) when resolving an array type, a method type (5.4.3.5), or a method handle (5.4.3.5).
If steps 1 and 2 succeed but step 3 fails, C is still valid and usable. Nevertheless, resolution fails, and D is prohibited from accessing C. If type resolution 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, that symbolic reference to a type is invalid.
To resolve an unresolved symbolic reference from D to a field in a class or interface C type T, the symbolic reference to C T given by the field reference must first be resolved (5.4.3.1). Therefore, any exception that can be thrown as a result of failure of resolution of a class or interface reference type can be thrown as a result of failure of field resolution. If the reference to C T can be successfully resolved, an exception relating to the failure of resolution of the field reference itself can be thrown.
Next, the class or interface named by T, C, is designated as the class or interface to search.
When resolving a field reference, field resolution first Field resolution then attempts to look up the referenced field in C and its superclasses:
If C declares a field with the name and descriptor specified by the field reference, field lookup succeeds. The declared field is the result of the field lookup.
Otherwise, field lookup is applied recursively to the direct superinterfaces of the specified class or interface C.
Otherwise, if C has a superclass S, field lookup is applied recursively to S.
Otherwise, field lookup fails.
Then:
If field lookup fails, field resolution throws a NoSuchFieldError
.
Otherwise, if field lookup succeeds but the referenced field is not accessible (5.4.4) to D, field resolution throws an IllegalAccessError
.
Otherwise, let <E, L₁> be the class or interface in which the referenced field is actually declared and let L₂ be the defining loader of D.
Given that the type of the referenced field is Tf, let T be Tf if Tf is not an array type, and let T be the element type (2.4) of Tf otherwise.
For each class or interface name N mentioned by the descriptor of the referenced field, the Java Virtual Machine must impose the loading constraint that N^L₁ = N^L₂ (5.3.4).
To resolve an unresolved symbolic reference from D to a method in the reference class type T of a class C, the symbolic reference to C T given by the method reference is first resolved (5.4.3.1). Therefore, any exception that can be thrown as a result of failure of resolution of a class reference type can be thrown as a result of failure of method resolution. If the reference to C T can be successfully resolved, exceptions relating to the resolution of the method reference itself can be thrown.
...
The result of method resolution is determined by whether method lookup succeeds or fails:
If method lookup fails, method resolution throws a NoSuchMethodError
.
Otherwise, if method lookup succeeds and the referenced method is not accessible (5.4.4) to D, method resolution throws an IllegalAccessError
.
Otherwise, let <E, L₁> be the class or interface in which the referenced method m is actually declared and let L₂ be the defining loader of D.
Given that the return type of m is Tr, and that the formal parameter types of m are Tf1, ..., Tfn, then:
If Tr is not an array type, let T0 be Tr; otherwise, let T0 be the element type (2.4) of Tr.
For i = 1 to n: If Tfi is not an array type, let Ti be Tfi; otherwise, let Ti be the element type (2.4) of Tfi.
For each class or interface name N mentioned by the descriptor of the referenced method, the Java Virtual Machine must impose the loading constraints Ti^L₁ = Ti^L₂ for i = 0 to n constraint N^L₁ = N^L₂ (5.3.4).
...
To resolve an unresolved symbolic reference from D to an interface method in the interface type T of an interface C, the symbolic reference to C T given by the interface method reference is first resolved (5.4.3.1). Therefore, any exception that can be thrown as a result of failure of resolution of an interface reference a type can be thrown as a result of failure of method resolution. If the reference to C T can be successfully resolved, exceptions relating to the resolution of the interface method reference itself can be thrown.
...
The result of interface method resolution is determined by whether method lookup succeeds or fails:
If method lookup fails, method resolution throws a NoSuchMethodError
.
Otherwise, if method lookup succeeds and the referenced method is not accessible (5.4.4) to D, interface method resolution throws an IllegalAccessError
.
Otherwise, let <E, L₁> be the class or interface in which the referenced method m is actually declared and let L₂ be the defining loader of D.
Given that the return type of m is Tr, and that the formal parameter types of m are Tf1, ..., Tfn, then:
If Tr is not an array type, let T0 be Tr; otherwise, let T0 be the element type (2.4) of Tr.
For i = 1 to n: If Tfi is not an array type, let Ti be Tfi; otherwise, let Ti be the element type (2.4) of Tfi.
For each class or interface name N mentioned by the descriptor of the referenced method, the Java Virtual Machine must impose the loading constraints Ti^L₁ = Ti^L₂ for i = 0 to n constraint N^L₁ = N^L₂ (5.3.4).
...
To resolve an unresolved symbolic reference to a method type, it is as if resolution occurs of unresolved symbolic references to classes and interfaces (5.4.3.1) whose names correspond to the types given in the method descriptor (4.3.3).
Any exception that can be thrown as a result of failure of resolution of a class reference type can thus be thrown as a result of failure of method type resolution.
The result of successful method type resolution is a reference to an instance of java.lang.invoke.MethodType
which represents the method descriptor.
Method type resolution occurs regardless of whether the run time constant pool actually contains symbolic references to
classes and interfacestypes 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 type in which the field or method is to be found.
...
Let MH be the symbolic reference to a method handle (5.1) being resolved. Then:
Let R be the symbolic reference to the field or method contained within MH.
R is derived from the
CONSTANT_Fieldref
,CONSTANT_Methodref
, orCONSTANT_InterfaceMethodref
structure referred to by thereference_index
item of theCONSTANT_MethodHandle
from which MH is derived.
Let T be the type of the field referenced by R, or the return type of the method referenced by R. Let A* be the sequence (perhaps empty) of parameter types of the method referenced by R.
T and A* are derived from the
CONSTANT_NameAndType
structure referred to by thename_and_type_index
item in theCONSTANT_Fieldref
,CONSTANT_Methodref
, orCONSTANT_InterfaceMethodref
structure from which R is derived.
To resolve MH, all symbolic references to classes, interfaces types, fields, and methods in MH's bytecode behavior are resolved, using the following three steps:
First, R is resolved.
Second, resolution occurs as if of unresolved symbolic references to classes and interfaces whose names correspond to each type in A*, and to the type T, in that order.
Third, 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.
In each step, any exception that can be thrown as a result of failure of resolution of a class or interface type or field or method reference can be thrown as a result of failure of method handle resolution.
The intent is that resolving a method handle can be done in exactly the same circumstances that the Java Virtual Machine would successfully resolve the symbolic references in the bytecode behavior. In particular, method handles to private and protected members can be created in exactly those classes for which the corresponding normal accesses are legal.
...
Initialization of a class or interface consists of executing its class or interface initialization method (2.9).
A class or interface C may be initialized only as a result of:
The execution of any one of the Java Virtual Machine instructions new
, getstatic
, putstatic
, or invokestatic
, vbox
, or vdefault
that references a class or interface type of C (new
, getstatic
, putstatic
, invokestatic
, vbox
, vdefault
). These instructions reference a class or interface type directly or indirectly through either a field reference or a method reference.
Upon execution of a new
or vdefault
instruction, the referenced class is initialized if it has not been initialized already.
Upon execution of a getstatic
, putstatic
, or invokestatic
instruction, the class or interface that declared the resolved field or method is initialized if it has not been initialized already.
The execution of the Java Virtual Machine instruction anewarray
(anewarray
), where the referenced component type is the direct value class type of C.
An array of a direct value class type initially holds default value instances of the class, so the class should be initialized. In contrast, an array of a reference class type initially holds
null
references, not class instances, so initialization is unnecessary.
The execution of the Java Virtual Machine instruction multianewarray
(multianewarray
), where the element type of the referenced array type is the direct value class type of C, and the dimensions parameter of the instruction is equal to the array type's number of dimensions.
This is true even if one of the count stack arguments is 0, preventing allocation of any arrays of the direct value class type.
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 (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 a class, its designation as the initial class at Java Virtual Machine startup (5.2).
Prior to initialization, a class or interface must be linked, that is, verified, prepared, and optionally resolved.
Because the Java Virtual Machine is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time. There is also the possibility that initialization of a class or interface may be requested recursively as part of the initialization of that class or interface. The implementation of the Java Virtual Machine is responsible for taking care of synchronization and recursive initialization by using the following procedure. It assumes that the class or interface has already been verified and prepared, and that the Class
object class or interface contains state that indicates one of four situations:Class
object
Class
objectClass
objectClass
objectClass
objectHere and below, we eliminate the unnecessary assertion that the initialization state of the class is stored by an instance of java.lang.Class
. The specification need not concern itself with how classes are internally represented and how this representation relates to instances of java.lang.Class
.
For each class or interface C, there is a unique initialization lock LC. The mapping from C to LC is left to the discretion of the Java Virtual Machine implementation. For example, LC could be the Class
object for a class or interface type of 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 the 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.Class
object for
Thread interrupt status is unaffected by execution of the initialization procedure.
If the 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.Class
object for
If the C indicates that C has already been initialized, then no further action is required. Release LC and complete normally.Class
object for
If the C is in an erroneous state, then initialization is not possible. Release LC and throw a Class
object forNoClassDefFoundError
.
Otherwise, record the fact that initialization of the C is in progress by the current thread, and release LC.Class
object for
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, and its superclass has not yet been initialized, 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 ], 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 the C as erroneous, notify all waiting threads, release LC, and complete abruptly, throwing the same exception that resulted from initializing SC.Class
object for
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 C as fully initialized, notify all waiting threads, release LC, and complete this procedure normally.Class
object for
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 the 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.Class
object for
A Java Virtual Machine implementation may optimize this procedure by eliding the lock acquisition in step 1 (and release in step 4/5) when it can determine that the initialization of the class has already completed, provided that, in terms of the Java memory model, all happens-before orderings (JLS 17.4.5) that would exist if the lock were acquired, still exist when the optimization is performed.
anewarray
Create a 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 item at that index must be a symbolic reference to a class, array, or interface type. The named class, array, or interface type is resolved (5.4.3.1), yielding the array component type.
If the referenced component type is a direct value class type, the named class is initialized (5.5) if that class has not already been initialized.
A new array with components of that type the referenced 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 reference
null, the default value for reference types (2.4) of the component type (2.3.5, 2.4).
During resolution of the symbolic reference to the class, array, or interface component type, any of the exceptions documented in 5.4.3.1 can be thrown.
Otherwise, if count is less than zero, the anewarray
instruction throws a NegativeArraySizeException
.
Otherwise, if execution of this anewarray
instruction causes initialization of a value class, anewarray
may throw an Error
as detailed in 5.5.
The anewarray
instruction is used to create a single dimension of an array of object references one-dimensional array or part of a multidimensional array.
The newarray
instruction is used to create an array with a primitive component type.
The anewarray
opcode may only be used to create an array of a direct value class type in a version 54.1 class file (4.4.1).
getfield
Fetch a field from object a class instance
getfield indexbyte1 indexbyte2
getfield = 180 (0xb4)
...,
objectrefvalue →
...,valueresult
The objectref, which must be of type 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 item at that 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 reference
, is popped from the operand stack.class type in which the field is to be found. The referenced field is resolved (5.4.3.2).
The value, which must be of the referenced type, is popped from the operand stack. The value value of the referenced field in objectref value, result, is fetched and pushed onto the operand stack.
The type of objectref must not be an array type. If the field is protected
, and it is a member of a superclass of the current class, and the field is not declared in the same run-time package (5.3) as the current class, then the class of objectref value must be either the current class or a subclass of the current class.
If the value has an array type, errors will occur (for example, verification may report that the array type may not be a subtype of the referenced type). But there's no need for a specific prohibition against array types.
During resolution of the symbolic reference to the field, any of the errors pertaining to field resolution (5.4.3.2) can be thrown.
Otherwise, if the resolved field is a static
field, getfield
throws an IncompatibleClassChangeError
.
Otherwise, if objectref value is null
, the getfield
instruction throws a NullPointerException
.
The getfield
instruction cannot be used to access the length of an array. The length
fieldarraylength
instruction (arraylength
) is used instead.
The getfield
opcode may only be used to access a field of a direct value class instance in a version 54.1 class file (4.4.2).
multianewarray
Create a 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 is the second, etc. All of the count values are popped off the operand stack.
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 item at that index must be a symbolic reference to a class, array, or interface type an array type. The named class, array, or interface type array type is resolved (5.4.3.1). The resulting entry must be an array class type of dimensionality greater than or equal to dimensions.
If the referenced array type's element type is a direct value class type, and if the number of dimensions of the array type is equal to dimensions, the named class is initialized (5.5) if that class has not already been initialized.
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.3.5, 2.4) for the element type of the array type that component type. A reference arrayref to the new array is pushed onto the operand stack.reference
During resolution of the symbolic reference to the class, array, or interface type array type, any of the exceptions documented in 5.4.3.1 can be thrown.
Otherwise, if the current class does not have permission to access the element type of the resolved array class, multianewarray
throws an IllegalAccessError
.
Otherwise, if any of the dimensions values on the operand stack are less than zero, the multianewarray
instruction throws a NegativeArraySizeException
.
Otherwise, if execution of this multianewarray
instruction causes initialization of a value class, multianewarray
may throw an Error
as detailed in 5.5.
It may be more efficient to use newarray
or anewarray
([newarray
], anewarray
) when creating an array of a single dimension.
The array class 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.
The multianewarray
opcode may only be used to create an array with a direct value class element type in a version 54.1 class file (4.4.1).
new
...
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 item at the index must be a symbolic reference to a reference class or interface type. The named class or interface type is resolved (5.4.3.1) and should result in a reference class type. 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 their default initial values (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 (5.5) if it has not already been initialized.
...
vaload
Load a direct value class instance from an array
vaload indexbyte1 indexbyte2
vaload = 205 (0xcd)
..., arrayref, index →
..., value
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 item at that index must be a symbolic reference to a direct value class type (4.4.1). The type is resolved (5.4.3.1).
The arrayref must be of type reference
and must refer to an array whose components are of the referenced type. The index must be of type int
.
Both arrayref and index are popped from the operand stack. The direct value class instance in the component of the array at index is retrieved and pushed onto the operand stack.
During resolution of the symbolic reference to the class or interface type, any of the exceptions documented in 5.4.3.1 can be thrown.
Otherwise, if arrayref is null
, vaload
throws a NullPointerException
.
Otherwise, if index is not within the bounds of the array referenced by arrayref, the vaload instruction throws an ArrayIndexOutOfBoundsException
.
The vaload
opcode may only appear in version 54.1 class files (4.9.1).
vastore
Store a direct value class instance into an array
vastore indexbyte1 indexbyte2
vastore = 206 (0xce)
..., arrayref, index, value →
...
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 item at that index must be a symbolic reference to a direct value class type (4.4.1). The type is resolved (5.4.3.1).
The arrayref must be of type reference
and must refer to an array whose components are of the referenced type. The index must be of type int
. The value must be of the referenced type.
The arrayref, index, and value are popped from the operand stack. The value is stored as the component of the array indexed by index.
If arrayref is null
, vastore
throws a NullPointerException
.
Otherwise, if index is not within the bounds of the array referenced by arrayref, the vastore instruction throws an ArrayIndexOutOfBoundsException
.
The vastore
opcode may only appear in version 54.1 class files (4.9.1).
vbox
Convert a direct value class instance to a reference class instance
vbox indexbyte1 indexbyte2
vbox = 216 (0xd6)
..., value →
..., 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 item at that index must be a symbolic reference to a reference class or interface type (4.4.1). The type is resolved (5.4.3.1).
Let C be class or interface named by the referenced type. C must be a value-capable class (4.7.25). C is initialized (5.5) if that class has not already been initialized.
The value on the top of the operand stack must be a direct value class instance; the class of which value is an instance must have been derived from C (5.3). The value is popped from the operand stack and converted to an object stored in the garbage-collected heap that is an instance of C, with fields storing the same values as value. A reference to the object, objectref, is pushed onto the operand stack.
During resolution of the symbolic reference to the class or interface type, any of the exceptions documented in 5.4.3.1 can be thrown.
Otherwise, if C is not a value-capable class, vbox
throws an IncompatibleClassChangeError
.
Otherwise, if execution of this vbox
instruction causes initialization of the referenced class, vbox
may throw an Error
as detailed in 5.5.
Otherwise, if the class of value was not derived from C, vbox
throws an IncompatibleClassChangeError
.
This check could be enforced at verification, but we prefer to keep the details of the mapping from value-capable classes to value classes out of the verification rules. Instead, verification ensures that the value has type valueClass
, and then at run time we ensure that each input has the expected direct value class type.
The vbox
opcode may only appear in version 54.1 class files (4.9.1).
A Java Virtual Machine implementation may choose to allocate new memory from the garbage-collected heap on each execution of a vbox
instruction. Alternatively, a Java Virtual Machine implementation may choose to re-use an existing object without allocating any new memory.
The new
instruction may also be used to create a reference to an instance of a value-capable class. In contrast to new
, the result of vbox
is already initialized and does not need to have an instance initialization method invoked.
vdefault
Push the default value of a direct value class type
vdefault indexbyte1 indexbyte2
vdefault = 214 (0xd6)
... →
..., value
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 item at that index must be a symbolic reference to a direct value class type (4.4.1). The type is resolved (5.4.3.1).
The named class is initialized (5.5) if that class has not already been initialized. The default value (2.3.5) of the direct value class type is pushed onto the operand stack.
During resolution of the symbolic reference to the class or interface type, any of the exceptions documented in 5.4.3.1 can be thrown.
Otherwise, if execution of this vdefault
instruction causes initialization of the referenced class, vdefault
may throw an Error
as detailed in 5.5.
The vdefault
opcode may only appear in version 54.1 class files (4.9.1).
A Java Virtual Machine implementation may choose to store the representation of the direct value in the operand stack, or may choose to allocate space for it in the heap (2.7).
vload
Load a direct value class instance from a local variable
vload index
vload = 203 (0xcb)
... →
..., value
The index is an unsigned byte that must be an index into the local variable array of the current frame (2.6). The local variable at index must contain a direct value class instance. The value in the local variable at index is pushed onto the operand stack.
The vload
opcode may only appear in version 54.1 class files (4.9.1).
The vload
opcode can be used in conjunction with the wide instruction (wide
) to access a local variable using a two-byte unsigned index.
vreturn
Return a direct value class instance from a method
vreturn
vload = 210 (0xd2)
..., value →
[empty]
The return type of the current method must be a direct value class type, V. The value must be of type V.
If the current method is a synchronized
method, the monitor entered or reentered on invocation of the method is updated and possibly exited as if by execution of a monitorexit
instruction (monitorexit
) in the current thread. If no exception is thrown, value is popped from the operand stack of the current frame (2.6) and pushed onto the operand stack of the frame of the invoker. Any other values on the operand stack of the current method are discarded.
The interpreter then returns control to the invoker of the method, reinstating the frame of the invoker.
If the Java Virtual Machine implementation does not enforce the rules on structured locking described in 2.11.10, then if the current method is a synchronized
method and the current thread is not the owner of the monitor entered or reentered on invocation of the method, vreturn
throws an IllegalMonitorStateException
. This can happen, for example, if a synchronized
method contains a monitorexit
instruction, but no monitorenter
instruction, on the object on which the method is synchronized.
Otherwise, if the Java Virtual Machine implementation enforces the rules on structured locking described in 2.11.10 and if the first of those rules is violated during invocation of the current method, then vreturn
throws an IllegalMonitorStateException
.
The vreturn
opcode may only appear in version 54.1 class files (4.9.1).
vstore
Store a direct value class instance into a local variable
vstore index
vstore = 204 (0xcc)
..., value→
...
The index is an unsigned byte that must be an index into the local variable array of the current frame (2.6). The value on the top of the operand stack must be a direct value class instance. It is popped from the operand stack, and the value of the local variable at index is set to value.
The vstore
opcode may only appear in version 54.1 class files (4.9.1).
The vstore
opcode can be used in conjunction with the wide instruction (wide
) to access a local variable using a two-byte unsigned index.
vunbox
Convert a reference class instance to a direct value class instance
vunbox indexbyte1 indexbyte2
vunbox = 217 (0xd7)
..., objectref →
..., value
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 item at that index must be a symbolic reference to a direct value class type (4.4.1). The type is resolved (5.4.3.1).
Let V be the value class named by the referenced type.
The objectref on the top of the operand stack must be a a reference to an instance of the value-capable class from which V was derived (5.3). It is popped from the operand stack and converted to a direct value class instance of V, value, with fields storing the same values as objectref. The value is pushed onto the operand stack.
During resolution of the symbolic reference to the direct value class type, any of the exceptions documented in 5.4.3.1 can be thrown.
Otherwise, if objectref is null
, the vunbox
instruction throws a NullPointerException
.
Otherwise, if the objectref is not a reference to an instance of the value-capable class from which V was derived, vunbox
throws an IncompatibleClassChangeError
.
This check could be enforced at verification, but we prefer to keep the details of the mapping from value-capable classes to value classes out of the verification rules. Instead, verification ensures that the objectref has type reference
, and then at run time we ensure that each input has the expected class type.
The vunbox
opcode may only appear in version 54.1 class files (4.9.1).
A Java Virtual Machine implementation may choose to store the representation of the direct value in the operand stack, or may choose to allocate space for it in the heap (2.7).
vwithfield
Derive a direct value class instance from another, modifying a field
vwithfield indexbyte1 indexbyte2
vwithfield = 215 (0xd7)
..., value1, value2 →
..., result
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 item at that 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 direct value class type in which the field is to be found. The referenced field is resolved (5.4.3.2).
The type of value1 must be the direct value class type appearing in the field reference. The type of value2 must be compatible with the descriptor of the referenced field (4.3.2).
The values value1
and value2
are popped from the operand stack. value2
undergoes value set conversion (2.8.3), resulting in value2'
. A new direct value class instance, result, is produced, with the referenced field storing value2'
, and all other fields storing their corresponding field values in value1
. The result is pushed onto the operand stack.
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 class named by the referenced direct value class type is neither the current class nor a value class derived from the current class (5.3), the vwithfield
instruction throws an IllegalAccessError
.
The vwithfield
opcode may only appear in version 54.1 class files (4.9.1).
A Java Virtual Machine implementation may choose to store the representation of the direct value in the operand stack, or may choose to allocate space for it in the heap (2.7).
The ability to create direct value class instances with the vwithfield
instruction is limited. This gives the value-capable class some control over the valid set of direct value class instances, while still permitting read access to the instances' fields (getfield
). Note, however, that the vdefault
, newarray
, and vunbox
instructions may also be used to create direct value class instances, and these instructions do not enforce any access restrictions.
wide
Extend local variable index by additional bytes
wide
indexbyte1 indexbyte2
where iload
, fload
, aload
, vload
, lload
, dload
, istore
, fstore
, astore
, vstore
, lstore
, dstore
, or ret
wide iinc indexbyte1 indexbyte2 constbyte1 constbyte2
wide = 196 (0xc4)
Same as modified instruction
The wide
instruction modifies the behavior of another instruction. It takes one of two formats, depending on the instruction being modified. The first form of the wide
instruction modifies one of the instructions iload
, fload
, aload
, vload
, lload
, dload
, istore
, fstore
, astore
, vstore
, lstore
, dstore
, or ret
(iload
, fload
, aload
, vload
, lload
, dload
, istore
, fstore
, astore
, vstore
, lstore
, dstore
, ret
). The second form applies only to the iinc
instruction (iinc
).
In either case, the wide
opcode itself is followed in the compiled code by the opcode of the instruction wide
modifies. In either form, two unsigned bytes indexbyte1
and indexbyte2
follow the modified opcode and are assembled into a 16-bit unsigned index to a local variable in the current frame (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The calculated index must be an index into the local variable array of the current frame. Where the wide
instruction modifies an lload
, dload
, lstore
, or dstore
instruction, the index following the calculated index (index + 1) must also be an index into the local variable array. In the second form, two immediate unsigned bytes constbyte1 and constbyte2 follow indexbyte1 and indexbyte2 in the code stream. Those bytes are also assembled into a signed 16-bit constant, where the constant is (constbyte1 << 8) | constbyte2.
The widened bytecode operates as normal, except for the use of the wider index and, in the case of the second form, the larger increment range.
Although we say that wide
"modifies the behavior of another instruction," the wide
instruction effectively treats the bytes constituting the modified instruction as operands, denaturing the embedded instruction in the process. In the case of a modified iinc
instruction, one of the logical operands of the iinc
is not even at the normal offset from the opcode. The embedded instruction must never be executed directly; its opcode must never be the target of any control transfer instruction.
Copyright © 2017 Oracle America, Inc. 4150 Network Circle, Santa Clara, California 95054, U.S.A. All rights reserved.
The Specification is protected by copyright and the information described therein may be protected by one or more U.S. patents, foreign patents, or pending applications. Except as provided under the following license, no part of the Specification may be reproduced in any form by any means without the prior written authorization of Oracle America, Inc. ("Oracle") and its licensors, if any. Any use of the Specification and the information described therein will be governed by the terms and conditions of this Agreement.
Subject to the terms and conditions of this license, including your compliance with Paragraphs 1 and 2 below, Oracle hereby grants you a fully-paid, non-exclusive, non-transferable, limited license (without the right to sublicense) under Oracle's intellectual property rights to:
Review the Specification for the purposes of evaluation. This includes: (i) developing implementations of the Specification for your internal, non-commercial use; (ii) discussing the Specification with any third party; and (iii) excerpting brief portions of the Specification in oral or written communications which discuss the Specification provided that such excerpts do not in the aggregate constitute a significant portion of the Technology.
Distribute implementations of the Specification to third parties for their testing and evaluation use, provided that any such implementation:
does not modify, subset, superset or otherwise extend the Licensor Name Space, or include any public or protected packages, classes, Java interfaces, fields or methods within the Licensor Name Space other than those required/authorized by the Specification or Specifications being implemented;
is clearly and prominently marked with the word "UNTESTED" or "EARLY ACCESS" or "INCOMPATIBLE" or "UNSTABLE" or "BETA" in any list of available builds and in proximity to every link initiating its download, where the list or link is under Licensee's control; and
includes the following notice: "This is an implementation of an early-draft specification developed under the Java Community Process (JCP) and is made available for testing and evaluation purposes only. The code is not compatible with any specification of the JCP."
The grant set forth above concerning your distribution of implementations of the specification is contingent upon your agreement to terminate development and distribution of your "early draft" implementation as soon as feasible following final completion of the specification. If you fail to do so, the foregoing grant shall be considered null and void.
No provision of this Agreement shall be understood to restrict your ability to make and distribute to third parties applications written to the Specification.
Other than this limited license, you acquire no right, title or interest in or to the Specification or any other Oracle intellectual property, and the Specification may only be used in accordance with the license terms set forth herein. This license will expire on the earlier of: (a) two (2) years from the date of Release listed above; (b) the date on which the final version of the Specification is publicly released; or (c) the date on which the Java Specification Request (JSR) to which the Specification corresponds is withdrawn. In addition, this license will terminate immediately without notice from Oracle if you fail to comply with any provision of this license. Upon termination, you must cease use of or destroy the Specification.
"Licensor Name Space" means the public class or interface declarations whose names begin with "java", "javax", "com.oracle" or their equivalents in any subsequent naming convention adopted by Oracle through the Java Community Process, or any recognized successors or replacements thereof.
No right, title, or interest in or to any trademarks, service marks, or trade names of Oracle or Oracle's licensors is granted hereunder. Oracle, the Oracle logo, Java are trademarks or registered trademarks of Oracle USA, Inc. in the U.S. and other countries.
THE SPECIFICATION IS PROVIDED "AS IS" AND IS EXPERIMENTAL AND MAY CONTAIN DEFECTS OR DEFICIENCIES WHICH CANNOT OR WILL NOT BE CORRECTED BY ORACLE. ORACLE MAKES NO REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT THAT THE CONTENTS OF THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE OR THAT ANY PRACTICE OR IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADE SECRETS OR OTHER RIGHTS. This document does not represent any commitment to release or implement any portion of the Specification in any product.
THE SPECIFICATION COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION THEREIN; THESE CHANGES WILL BE INCORPORATED INTO NEW VERSIONS OF THE SPECIFICATION, IF ANY. ORACLE MAY MAKE IMPROVEMENTS AND/OR CHANGES TO THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THE SPECIFICATION AT ANY TIME. Any use of such changes in the Specification will be governed by the then-current license for the applicable version of the Specification.
TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL ORACLE OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES, INCLUDING WITHOUT LIMITATION, LOST REVENUE, PROFITS OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO ANY FURNISHING, PRACTICING, MODIFYING OR ANY USE OF THE SPECIFICATION, EVEN IF ORACLE AND/OR ITS LICENSORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
You will hold Oracle (and its licensors) harmless from any claims based on your use of the Specification for any purposes other than the limited right of evaluation as described above, and from any claims that later versions or releases of any Specification furnished to you are incompatible with the Specification provided to you under this license.
If this Software is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in the Software and accompanying documentation shall be only as set forth in this license; this is in accordance with 48 C.F.R. 227.7201 through 227.7202-4 (for Department of Defense (DoD) acquisitions) and with 48 C.F.R. 2.101 and 12.212 (for non-DoD acquisitions).
You may wish to report any ambiguities, inconsistencies or inaccuracies you may find in connection with your evaluation of the Specification ("Feedback"). To the extent that you provide Oracle with any Feedback, you hereby: (i) agree that such Feedback is provided on a non-proprietary and non-confidential basis, and (ii) grant Oracle a perpetual, non-exclusive, worldwide, fully paid-up, irrevocable license, with the right to sublicense through multiple levels of sublicensees, to incorporate, disclose, and use without limitation the Feedback for any purpose related to the Specification and future versions, implementations, and test suites thereof.
Any action related to this Agreement will be governed by California law and controlling U.S. federal law. The U.N. Convention for the International Sale of Goods and the choice of law rules of any jurisdiction will not apply.
The Specification is subject to U.S. export control laws and may be subject to export or import regulations in other countries. Licensee agrees to comply strictly with all such laws and regulations and acknowledges that it has the responsibility to obtain such licenses to export, re-export or import as may be required after delivery to Licensee.
This Agreement is the parties' entire agreement relating to its subject matter. It supersedes all prior or contemporaneous oral or written communications, proposals, conditions, representations and warranties and prevails over any conflicting or additional terms of any quote, order, acknowledgment, or other communication between the parties relating to its subject matter during the term of this Agreement. No modification to this Agreement will be binding, unless in writing and signed by an authorized representative of each party.