Movatterモバイル変換


[0]ホーム

URL:


Oracle Logo

Java SE >Java SE Specifications >Java Virtual Machine Specification

Chapter 4. Theclass File Format
Prev   Next

Chapter 4. Theclass File Format

Table of Contents

4.1. TheClassFile Structure
4.2. Names
4.2.1. Binary Class and Interface Names
4.2.2. Unqualified Names
4.2.3. Module and Package Names
4.3. Descriptors
4.3.1. Grammar Notation
4.3.2. Field Descriptors
4.3.3. Method Descriptors
4.4. The Constant Pool
4.4.1. TheCONSTANT_Class_info Structure
4.4.2. TheCONSTANT_Fieldref_info,CONSTANT_Methodref_info, andCONSTANT_InterfaceMethodref_info Structures
4.4.3. TheCONSTANT_String_info Structure
4.4.4. TheCONSTANT_Integer_info andCONSTANT_Float_info Structures
4.4.5. TheCONSTANT_Long_info andCONSTANT_Double_info Structures
4.4.6. TheCONSTANT_NameAndType_info Structure
4.4.7. TheCONSTANT_Utf8_info Structure
4.4.8. TheCONSTANT_MethodHandle_info Structure
4.4.9. TheCONSTANT_MethodType_info Structure
4.4.10. TheCONSTANT_Dynamic_info andCONSTANT_InvokeDynamic_info Structures
4.4.11. TheCONSTANT_Module_info Structure
4.4.12. TheCONSTANT_Package_info Structure
4.5. Fields
4.6. Methods
4.7. Attributes
4.7.1. Defining and Naming New Attributes
4.7.2. TheConstantValue Attribute
4.7.3. TheCode Attribute
4.7.4. TheStackMapTable Attribute
4.7.5. TheExceptions Attribute
4.7.6. TheInnerClasses Attribute
4.7.7. TheEnclosingMethod Attribute
4.7.8. TheSynthetic Attribute
4.7.9. TheSignature Attribute
4.7.9.1. Signatures
4.7.10. TheSourceFile Attribute
4.7.11. TheSourceDebugExtension Attribute
4.7.12. TheLineNumberTable Attribute
4.7.13. TheLocalVariableTable Attribute
4.7.14. TheLocalVariableTypeTable Attribute
4.7.15. TheDeprecated Attribute
4.7.16. TheRuntimeVisibleAnnotations Attribute
4.7.16.1. Theelement_value structure
4.7.17. TheRuntimeInvisibleAnnotations Attribute
4.7.18. TheRuntimeVisibleParameterAnnotations Attribute
4.7.19. TheRuntimeInvisibleParameterAnnotations Attribute
4.7.20. TheRuntimeVisibleTypeAnnotations Attribute
4.7.20.1. Thetarget_info union
4.7.20.2. Thetype_path structure
4.7.21. TheRuntimeInvisibleTypeAnnotations Attribute
4.7.22. TheAnnotationDefault Attribute
4.7.23. TheBootstrapMethods Attribute
4.7.24. TheMethodParameters Attribute
4.7.25. TheModule Attribute
4.7.26. TheModulePackages Attribute
4.7.27. TheModuleMainClass Attribute
4.7.28. TheNestHost Attribute
4.7.29. TheNestMembers Attribute
4.7.30. TheRecord Attribute
4.7.31. ThePermittedSubclasses Attribute
4.8. Format Checking
4.9. Constraints on Java Virtual Machine Code
4.9.1. Static Constraints
4.9.2. Structural Constraints
4.10. Verification ofclass Files
4.10.1. Verification by Type Checking
4.10.1.1. Accessors for Java Virtual Machine Artifacts
4.10.1.2. Verification Type System
4.10.1.3. Instruction Representation
4.10.1.4. Stack Map Frames and Type Transitions
4.10.1.5. Type Checking Abstract and Native Methods
4.10.1.6. Type Checking Methods with Code
4.10.1.7. Type Checking Load and Store Instructions
4.10.1.8. Type Checking forprotected Members
4.10.1.9. Type Checking Instructions
aaload
aastore
aconst_null
aload,aload_<n>
anewarray
areturn
arraylength
astore,astore_<n>
athrow
baload
bastore
bipush
caload
castore
checkcast
d2f,d2i,d2l
dadd
daload
dastore
dcmp<op>
dconst_<d>
ddiv
dload,dload_<n>
dmul
dneg
drem
dreturn
dstore,dstore_<n>
dsub
dup
dup_x1
dup_x2
dup2
dup2_x1
dup2_x2
f2d,f2i,f2l
fadd
faload
fastore
fcmp<op>
fconst_<f>
fdiv
fload,fload_<n>
fmul
fneg
frem
freturn
fstore,fstore_<n>
fsub
getfield
getstatic
goto,goto_w
i2b,i2c,i2d,i2f,i2l,i2s
iadd
iaload
iand
iastore
iconst_<i>
idiv
if_acmp<cond>
if_icmp<cond>
if<cond>
ifnonnull,ifnull
iinc
iload,iload_<n>
imul
ineg
instanceof
invokedynamic
invokeinterface
invokespecial
invokestatic
invokevirtual
ior,irem
ireturn
ishl,ishr,iushr
istore,istore_<n>
isub,ixor
l2d,l2f,l2i
ladd
laload
land
lastore
lcmp
lconst_<l>
ldc,ldc_w,ldc2_w
ldiv
lload,lload_<n>
lmul
lneg
lookupswitch
lor,lrem
lreturn
lshl,lshr,lushr
lstore,lstore_<n>
lsub,lxor
monitorenter,monitorexit
multianewarray
new
newarray
nop
pop,pop2
putfield
putstatic
return
saload
sastore
sipush
swap
tableswitch
wide
4.10.2. Verification by Type Inference
4.10.2.1. The Process of Verification by Type Inference
4.10.2.2. The Bytecode Verifier
4.10.2.3. Values of Typeslong anddouble
4.10.2.4. Instance Initialization Methods and Newly Created Objects
4.10.2.5. Exceptions andfinally
4.11. Limitations of the Java Virtual Machine

This chapter describes theclass file format of the Java Virtual Machine. Eachclass file contains the definition of a single class, interface, or module. Although a class, interface, or module need not have an external representation literally contained in a file (for instance, because the class is generated by a class loader), we will colloquially refer to any valid representation of a class, interface, or module as being in theclass file format.

Aclass file consists of a stream of 8-bit bytes. 16-bit and 32-bit quantities are constructed by reading in two and four consecutive 8-bit bytes, respectively. Multibyte data items are always stored in big-endian order, where the high bytes come first. This chapter defines the data typesu1,u2, andu4 to represent an unsigned one-, two-, or four-byte quantity, respectively.

In the Java SE Platform API, theclass file format is supported by interfacesjava.io.DataInput andjava.io.DataOutput and classes such asjava.io.DataInputStream andjava.io.DataOutputStream. For example, values of the typesu1,u2, andu4 may be read by methods such asreadUnsignedByte,readUnsignedShort, andreadInt of the interfacejava.io.DataInput.

This chapter presents theclass file format using pseudostructures written in a C-like structure notation. To avoid confusion with the fields of classes and class instances, etc., the contents of the structures describing theclass file format are referred to asitems. Successive items are stored in theclass file sequentially, without padding or alignment.

Tables, consisting of zero or more variable-sized items, are used in severalclass file structures. Although we use C-like array syntax to refer to table items, the fact that tables are streams of varying-sized structures means that it is not possible to translate a table index directly to a byte offset into the table.

Where we refer to a data structure as anarray, it consists of zero or more contiguous fixed-sized items and can be indexed like an array.

Reference to an ASCII character in this chapter should be interpreted to mean the Unicode code point corresponding to the ASCII character.

4.1. TheClassFile Structure

Aclass file consists of a singleClassFile 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 theClassFile structure are as follows:

magic

Themagic item supplies the magic number identifying theclass file format; it has the value0xCAFEBABE.

minor_version, major_version

The values of theminor_version andmajor_version items are the minor and major version numbers of thisclass file. Together, a major and a minor version number determine the version of theclass file format. If aclass file has major version numberM and minor version numberm, we denote the version of itsclass file format asM.m.

A Java Virtual Machine implementation which conforms to Java SEN must support exactly the major versions of theclass file format specified in the fourth column ofTable 4.1-A, "Supported majors". The notationA ..B means major versionsA throughB, inclusive of bothA andB. The third column, "Major", shows the major version introduced by each Java SE release, that is, the first release that could have accepted aclass file containing thatmajor_version item. For very early releases, the JDK version is shown instead of the Java SE release.

Table 4.1-A. class file format major versions

Java SEReleasedMajorSupported majors
1.0.2May 19964545
1.1February 19974545
1.2December 19984645 .. 46
1.3May 20004745 .. 47
1.4February 20024845 .. 48
5.0September 20044945 .. 49
6December 20065045 .. 50
7July 20115145 .. 51
8March 20145245 .. 52
9September 20175345 .. 53

10

March 20185445 .. 54

11

September 20185545 .. 55

12

March 20195645 .. 56

13

September 20195745 .. 57

14

March 20205845 .. 58

15

September 20205945 .. 59

16

March 20216045 .. 60

17

September 20216145 .. 61

18

March 20226245 .. 62

19

September 20226345 .. 63

20

March 20236445 .. 64

21

September 20236545 .. 65

22

March 20246645 .. 66

23

September 20246745 .. 67

24

March 20256845 .. 68

For aclass file whosemajor_version is 56 or above, theminor_version must be 0 or 65535.

For aclass file whosemajor_version is between 45 and 55 inclusive, theminor_version may be any value.

A historical perspective is warranted on JDK support forclass file format versions. JDK 1.0.2 supported versions 45.0 through 45.3 inclusive. JDK 1.1 supported versions 45.0 through 45.65535 inclusive. When JDK 1.2 introduced support for major version 46, the only minor version supported under that major version was 0. Later JDKs continued the practice of introducing support for a new major version (47, 48, etc) but supporting only a minor version of 0 under the new major version. Finally, the introduction of preview features in Java SE 12 (see below) motivated a standard role for the minor version of theclass file format, so JDK 12 supported minor versions of 0and 65535 under major version 56. Subsequent JDKs introduce support forN.0 andN.65535 whereN is the corresponding major version of the implemented Java SE Platform. For example, JDK 13 supports 57.0 and 57.65535.

The Java SE Platform may definepreview features. A Java Virtual Machine implementation which conforms to Java SEN (N 12) must support all the preview features of Java SEN, and none of the preview features of any other Java SE release. The implementation must by default disable the supported preview features, and must provide a way to enable all of them, and must not provide a way to enable only some of them.

Aclass file is said todepend on the preview features of Java SEN (N 12) if it has amajor_version that corresponds to Java SEN (according toTable 4.1-A) and aminor_version of 65535.

A Java Virtual Machine implementation which conforms to Java SEN (N 12) must behave as follows:

  • Aclass file that depends on the preview features of Java SEN may be loaded only when the preview features of Java SEN are enabled.

  • Aclass file that depends on the preview features of another Java SE release must never be loaded.

  • Aclass file that does not depend on the preview features of any Java SE release may be loaded regardless of whether the preview features of Java SEN are enabled.

constant_pool_count

The value of theconstant_pool_count item is equal to the number of entries in theconstant_pool table plus one. Aconstant_pool index is considered valid if it is greater than zero and less thanconstant_pool_count, with the exception for constants of typelong anddouble noted in§4.4.5.

constant_pool[]

Theconstant_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 theClassFile structure and its substructures. The format of eachconstant_pool table entry is indicated by its first "tag" byte.

Theconstant_pool table is indexed from 1 toconstant_pool_count - 1.

access_flags

The value of theaccess_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 inTable 4.1-B.

Table 4.1-B. Class access and property modifiers

Flag NameValueInterpretation
ACC_PUBLIC0x0001Declaredpublic; may be accessed from outside its package.
ACC_FINAL0x0010Declaredfinal; no subclasses allowed.
ACC_SUPER0x0020Treat superclass methods specially when invoked by theinvokespecial instruction.
ACC_INTERFACE0x0200Is an interface, not a class.
ACC_ABSTRACT0x0400Declaredabstract; must not be instantiated.
ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
ACC_ANNOTATION0x2000Declared as an annotation interface.
ACC_ENUM0x4000Declared as anenum class.

ACC_MODULE

0x8000Is a module, not a class or interface.

TheACC_MODULE flag indicates that thisclass file defines a module, not a class or interface. If theACC_MODULE flag is set, then special rules apply to theclass file which are given at the end of this section. If theACC_MODULE flag is not set, then the rules immediately below the current paragraph apply to theclass file.

An interface is distinguished by theACC_INTERFACE flag being set. If theACC_INTERFACE flag is not set, thisclass file defines a class, not an interface or module.

If theACC_INTERFACE flag is set, theACC_ABSTRACT flag must also be set, and theACC_FINAL,ACC_SUPER,ACC_ENUM, andACC_MODULE flags set must not be set.

If theACC_INTERFACE flag is not set, any of the other flags inTable 4.1-B may be set exceptACC_ANNOTATION andACC_MODULE. However, such aclass file must not have both itsACC_FINAL andACC_ABSTRACT flags set (JLS §8.1.1.2).

TheACC_SUPER flag indicates which of two alternative semantics is to be expressed by theinvokespecial instruction (§invokespecial) if it appears in this class or interface. Compilers to the instruction set of the Java Virtual Machine should set theACC_SUPER flag. In Java SE 8 and above, the Java Virtual Machine considers theACC_SUPER flag to be set in everyclass file, regardless of the actual value of the flag in theclass file and the version of theclass file.

TheACC_SUPER flag exists for backward compatibility with code compiled by older compilers for the Java programming language. Prior to JDK 1.0.2, the compiler generatedaccess_flags in which the flag now representingACC_SUPER had no assigned meaning, and Oracle's Java Virtual Machine implementation ignored the flag if it was set.

TheACC_SYNTHETIC flag indicates that this class or interface was generated by a compiler and does not appear in source code.

An annotation interface (JLS §9.6) must have itsACC_ANNOTATION flag set. If theACC_ANNOTATION flag is set, theACC_INTERFACE flag must also be set.

TheACC_ENUM flag indicates that this class or its superclass is declared as an enum class (JLS §8.9).

All bits of theaccess_flags item not assigned inTable 4.1-B are reserved for future use. They should be set to zero in generatedclass files and should be ignored by Java Virtual Machine implementations.

this_class

The value of thethis_class item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure (§4.4.1) representing the class or interface defined by thisclass file.

super_class

For a class, the value of thesuper_class item either must be zero or must be a valid index into theconstant_pool table. If the value of thesuper_class item is nonzero, theconstant_pool entry at that index must be aCONSTANT_Class_info structure representing the direct superclass of the class defined by thisclass file. Neither the direct superclass nor any of its superclasses may have theACC_FINAL flag set in theaccess_flags item of itsClassFile structure.

If the value of thesuper_class item is zero, then thisclass file must represent the classObject, the only class or interface without a direct superclass.

For an interface, the value of thesuper_class item must always be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure representing the classObject.

interfaces_count

The value of theinterfaces_count item gives the number of direct superinterfaces of this class or interface type.

interfaces[]

Each value in theinterfaces array must be a valid index into theconstant_pool table. Theconstant_pool entry at each value ofinterfaces[i], where 0i <interfaces_count, must be aCONSTANT_Class_info structure representing an interface that is a direct superinterface of this class or interface type, in the left-to-right order given in the source for the type.

fields_count

The value of thefields_count item gives the number offield_info structures in thefields table. Thefield_info structures represent all fields, both class variables and instance variables, declared by this class or interface type.

fields[]

Each value in thefields table must be afield_info structure (§4.5) giving a complete description of a field in this class or interface. Thefields table includes only those fields that are declared by this class or interface. It does not include items representing fields that are inherited from superclasses or superinterfaces.

methods_count

The value of themethods_count item gives the number ofmethod_info structures in themethods table.

methods[]

Each value in themethods table must be amethod_info structure (§4.6) giving a complete description of a method in this class or interface. If neither of theACC_NATIVE andACC_ABSTRACT flags are set in theaccess_flags item of amethod_info structure, the Java Virtual Machine instructions implementing the method are also supplied.

Themethod_info structures represent all methods declared by this class or interface type, including instance methods, class methods, instance initialization methods (§2.9.1), and any class or interface initialization method (§2.9.2). Themethods table does not include items representing methods that are inherited from superclasses or superinterfaces.

attributes_count

The value of theattributes_count item gives the number of attributes in theattributes table of this class.

attributes[]

Each value of theattributes table must be anattribute_info structure (§4.7).

The attributes defined by this specification as appearing in theattributes table of aClassFile structure are listed inTable 4.7-C.

The rules concerning attributes defined to appear in theattributes table of aClassFile structure are given in§4.7.

The rules concerning non-predefined attributes in theattributes table of aClassFile structure are given in§4.7.1.

If theACC_MODULE flag is set in theaccess_flags item, then no other flag in theaccess_flags item may be set, and the following rules apply to the rest of theClassFile structure:

  • major_version,minor_version: 53.0 (i.e., Java SE 9 and above)

  • this_class:module-info

  • super_class,interfaces_count,fields_count,methods_count: zero

  • attributes: OneModule attribute must be present. Except forModule,ModulePackages,ModuleMainClass,InnerClasses,SourceFile,SourceDebugExtension,RuntimeVisibleAnnotations, andRuntimeInvisibleAnnotations, none of the pre-defined attributes (§4.7) may appear.

4.2. Names

4.2.1. Binary Class and Interface Names

Class and interface names that appear inclass file structures are always represented in a fully qualified form known asbinary names (JLS §13.1). Such names are always represented asCONSTANT_Utf8_info structures (§4.4.7) and thus may be drawn, where not further constrained, from the entire Unicode codespace. Class and interface names are referenced from thoseCONSTANT_NameAndType_info structures (§4.4.6) which have such names as part of their descriptor (§4.3), and from allCONSTANT_Class_info structures (§4.4.1).

For historical reasons, the syntax of binary names that appear inclass file structures differs from the syntax of binary names documented in JLS §13.1. In this internal form, the ASCII periods (.) that normally separate the identifiers which make up the binary name are replaced by ASCII forward slashes (/). The identifiers themselves must be unqualified names (§4.2.2).

For example, the normal binary name of classThread isjava.lang.Thread. In the internal form used in descriptors in theclass file format, a reference to the name of classThread is implemented using aCONSTANT_Utf8_info structure representing the stringjava/lang/Thread.

4.2.2. Unqualified Names

Names of methods, fields, local variables, and formal parameters are stored asunqualified names. An unqualified name must contain at least one Unicode code point and must not contain any of the ASCII characters.;[/ (that is, period or semicolon or left square bracket or forward slash).

Method names are further constrained so that, with the exception of the special method names<init> and<clinit> (§2.9), they must not contain the ASCII characters< or> (that is, left angle bracket or right angle bracket).

Note that no method invocation instruction may reference<clinit>, and only theinvokespecial instruction (§invokespecial) may reference<init>.

4.2.3. Module and Package Names

Module names referenced from theModule attribute are stored inCONSTANT_Module_info structures in the constant pool (§4.4.11). ACONSTANT_Module_info structure wraps aCONSTANT_Utf8_info structure that denotes the module name. Module names are not encoded in "internal form" like class and interface names, that is, the ASCII periods (.) that separate the identifiers in a module name are not replaced by ASCII forward slashes (/).

Module names may be drawn from the entire Unicode codespace, subject to the following constraints:

  • A module name must not contain any code point in the range '\u0000' to '\u001F' inclusive.

  • The ASCII backslash (\) is reserved for use as an escape character in module names. It must not appear in a module name unless it is followed by an ASCII backslash, an ASCII colon (:), or an ASCII at-sign (@). The ASCII character sequence\\ may be used to encode a backslash in a module name.

  • The ASCII colon (:) and at-sign (@) are reserved for future use in module names. They must not appear in module names unless they are escaped. The ASCII character sequences\: and\@ may be used to encode a colon and an at-sign in a module name.

Package names referenced from theModule attribute are stored inCONSTANT_Package_info structures in the constant pool (§4.4.12). ACONSTANT_Package_info structure wraps aCONSTANT_Utf8_info structure that represents a package name encoded in internal form.

4.3. Descriptors

Adescriptor is a string representing the type of a field or method. Descriptors are represented in theclass file format using modified UTF-8 strings (§4.4.7) and thus may be drawn, where not further constrained, from the entire Unicode codespace.

4.3.1. Grammar Notation

Descriptors are specified using a grammar. The grammar is a set of productions that describe how sequences of characters can form syntactically correct descriptors of various kinds. Terminal symbols of the grammar are shown infixed width font, and should be interpreted as ASCII characters. Nonterminal symbols are shown initalic type. The definition of a nonterminal is introduced by the name of the nonterminal being defined, followed by a colon. One or more alternative definitions for the nonterminal then follow on succeeding lines.

The syntax{x} on the right-hand side of a production denotes zero or more occurrences ofx.

The phrase(one of) on the right-hand side of a production signifies that each of the terminal symbols on the following line or lines is an alternative definition.

4.3.2. Field Descriptors

Afield descriptor represents the type of a field, parameter, local variable, or value.

FieldDescriptor:
FieldType:
BaseType:
(one of)
BCDFIJSZ
ClassType:
L ClassName;
ArrayType:
ComponentType:

ClassName represents a binary class or interface name encoded in internal form (§4.2.1).

A field descriptormentions a class or interface name if the name appears as aClassName in the descriptor. This includes aClassName nested in theComponentType of anArrayType.

The interpretation of field descriptors as types is shown inTable 4.3-A. See§2.2,§2.3, and§2.4 for the meaning of these types.

A field descriptor representing an array type is valid only if it represents a type with 255 or fewer dimensions.

Table 4.3-A. Interpretation of field descriptors

FieldType termType
Bbyte
Cchar
Ddouble
Ffloat
Iint
Jlong
LClassName;

Named class or interface type

Sshort
Zboolean

[ComponentType

Array of given component type


The field descriptor of an instance variable of typeint is simplyI.

The field descriptor of an instance variable of typeObject 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 typedouble[][][] is[[[D.

4.3.3. Method Descriptors

Amethod descriptor contains zero or moreparameter descriptors, representing the types of parameters that the method takes, and areturn descriptor, representing the type of the value (if any) that the method returns.

MethodDescriptor:
ParameterDescriptor:
ReturnDescriptor:
VoidDescriptor:
V

The characterV indicates that the method returns no value (its result isvoid).

A method descriptormentions a class or interface name if the name appears as aClassName in theFieldType of a parameter descriptor or return descriptor.

The method descriptor for the method:

Object m(int i, double d, Thread t) {...}

is:

(IDLjava/lang/Thread;)Ljava/lang/Object;

Note that the internal forms of the binary names ofThread andObject are used.

A method descriptor is valid only if it represents method parameters with a total length of 255 or less, where that length includes the contribution forthis in the case of instance or interface method invocations. The total length is calculated by summing the contributions of the individual parameters, where a parameter of typelong ordouble contributes two units to the length and a parameter of any other type contributes one unit.

A method descriptor is the same whether the method it describes is a class method or an instance method. Although an instance method is passedthis, a reference to the object on which the method is being invoked, in addition to its intended arguments, that fact is not reflected in the method descriptor. The reference tothis is passed implicitly by the Java Virtual Machine instructions which invoke instance methods (§2.6.1,§4.11).

4.4. The Constant Pool

Java Virtual Machine instructions do not rely on the run-time layout of classes, interfaces, class instances, or arrays. Instead, instructions refer to symbolic information in theconstant_pool table.

Allconstant_pool table entries have the following general format:

cp_info {    u1 tag;    u1 info[];}

Each entry in theconstant_pool table must begin with a 1-byte tag indicating the kind of constant denoted by the entry. There are 17 kinds of constant, listed inTable 4.4-A with their corresponding tags, and ordered by their section number in this chapter. Each tag byte must be followed by two or more bytes giving information about the specific constant. The format of the additional information depends on the tag byte, that is, the content of theinfo array varies with the value oftag.

Table 4.4-A. Constant pool tags (by section)

Constant KindTagSection
CONSTANT_Class7§4.4.1
CONSTANT_Fieldref9§4.4.2
CONSTANT_Methodref10§4.4.2
CONSTANT_InterfaceMethodref11§4.4.2
CONSTANT_String8§4.4.3
CONSTANT_Integer3§4.4.4
CONSTANT_Float4§4.4.4
CONSTANT_Long5§4.4.5
CONSTANT_Double6§4.4.5
CONSTANT_NameAndType12§4.4.6
CONSTANT_Utf81§4.4.7
CONSTANT_MethodHandle15§4.4.8
CONSTANT_MethodType16§4.4.9
CONSTANT_Dynamic17§4.4.10
CONSTANT_InvokeDynamic18§4.4.10
CONSTANT_Module19§4.4.11
CONSTANT_Package20§4.4.12

In aclass file whose version number isv, each entry in theconstant_pool table must have a tag that was first defined in versionv or earlier of theclass file format (§4.1). That is, each entry must denote a kind of constant that is approved for use in theclass file.Table 4.4-B lists each tag with the first version of theclass file format in which it was defined. Also shown is the version of the Java SE Platform which introduced that version of theclass file format.

Table 4.4-B. Constant pool tags (by tag)

Constant KindTagclass file formatJava SE
CONSTANT_Utf8145.31.0.2
CONSTANT_Integer345.31.0.2
CONSTANT_Float445.31.0.2
CONSTANT_Long545.31.0.2
CONSTANT_Double645.31.0.2
CONSTANT_Class745.31.0.2
CONSTANT_String845.31.0.2
CONSTANT_Fieldref945.31.0.2
CONSTANT_Methodref1045.31.0.2
CONSTANT_InterfaceMethodref1145.31.0.2
CONSTANT_NameAndType1245.31.0.2
CONSTANT_MethodHandle1551.07
CONSTANT_MethodType1651.07
CONSTANT_Dynamic1755.011
CONSTANT_InvokeDynamic1851.07
CONSTANT_Module1953.09
CONSTANT_Package2053.09

Some entries in theconstant_pool table areloadable because they represent entities that can be pushed onto the stack at run time to enable further computation. In aclass file whose version number isv, an entry in theconstant_pool table is loadable if it has a tag that was first deemed to be loadable in versionv or earlier of theclass file format.Table 4.4-C lists each tag with the first version of theclass file format in which it was deemed to be loadable. Also shown is the version of the Java SE Platform which introduced that version of theclass file format.

In every case exceptCONSTANT_Class, a tag was first deemed to be loadable in the same version of theclass file format that first defined the tag.

Table 4.4-C. Loadable constant pool tags

Constant KindTagclass file formatJava SE
CONSTANT_Integer345.31.0.2
CONSTANT_Float445.31.0.2
CONSTANT_Long545.31.0.2
CONSTANT_Double645.31.0.2
CONSTANT_Class749.05.0
CONSTANT_String845.31.0.2
CONSTANT_MethodHandle1551.07
CONSTANT_MethodType1651.07
CONSTANT_Dynamic1755.011

4.4.1. TheCONSTANT_Class_info Structure

TheCONSTANT_Class_info structure is used to represent a class or an interface:

CONSTANT_Class_info {    u1 tag;    u2 name_index;}

The items of theCONSTANT_Class_info structure are as follows:

tag

Thetag item has the valueCONSTANT_Class (7).

name_index

The value of thename_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing a valid binary class or interface name encoded in internal form (§4.2.1).

Because arrays are objects, the opcodesanewarray andmultianewarray - but not the opcodenew - can reference array "classes" viaCONSTANT_Class_info structures in theconstant_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;.

An array type descriptor is valid only if it represents 255 or fewer dimensions.

4.4.2. TheCONSTANT_Fieldref_info,CONSTANT_Methodref_info, andCONSTANT_InterfaceMethodref_info Structures

Fields, 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

Thetag item of aCONSTANT_Fieldref_info structure has the valueCONSTANT_Fieldref (9).

Thetag item of aCONSTANT_Methodref_info structure has the valueCONSTANT_Methodref (10).

Thetag item of aCONSTANT_InterfaceMethodref_info structure has the valueCONSTANT_InterfaceMethodref (11).

class_index

The value of theclass_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure (§4.4.1) representing a class or interface type that has the field or method as a member.

In aCONSTANT_Fieldref_info structure, theclass_index item may be either a class type or an interface type.

In aCONSTANT_Methodref_info structure, theclass_index item should be a class type, not an interface type.

In aCONSTANT_InterfaceMethodref_info structure, theclass_index item should be an interface type, not a class type.

name_and_type_index

The value of thename_and_type_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_NameAndType_info structure (§4.4.6). Thisconstant_pool entry indicates the name and descriptor of the field or method.

In aCONSTANT_Fieldref_info structure, the indicated descriptor must be a field descriptor (§4.3.2). Otherwise, the indicated descriptor must be a method descriptor (§4.3.3).

If the name of the method in aCONSTANT_Methodref_info structure begins with a '<' ('\u003c'), then the name must be the special name<init>, representing an instance initialization method (§2.9.1). The return type of such a method must bevoid.

4.4.3. TheCONSTANT_String_info Structure

TheCONSTANT_String_info structure is used to represent constant objects of the typeString:

CONSTANT_String_info {    u1 tag;    u2 string_index;}

The items of theCONSTANT_String_info structure are as follows:

tag

Thetag item has the valueCONSTANT_String (8).

string_index

The value of thestring_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the sequence of Unicode code points to which theString object is to be initialized.

4.4.4. TheCONSTANT_Integer_info andCONSTANT_Float_info Structures

TheCONSTANT_Integer_info andCONSTANT_Float_info structures represent 4-byte numeric (int andfloat) constants:

CONSTANT_Integer_info {    u1 tag;    u4 bytes;}CONSTANT_Float_info {    u1 tag;    u4 bytes;}

The items of these structures are as follows:

tag

Thetag item of theCONSTANT_Integer_info structure has the valueCONSTANT_Integer (3).

Thetag item of theCONSTANT_Float_info structure has the valueCONSTANT_Float (4).

bytes

Thebytes item of theCONSTANT_Integer_info structure represents the value of theint constant. The bytes of the value are stored in big-endian (high byte first) order.

Thebytes item of theCONSTANT_Float_info structure represents the value of thefloat constant in IEEE 754 binary32 floating-point format (§2.3.2). The bytes of the item are stored in big-endian (high byte first) order.

The value represented by theCONSTANT_Float_info structure is determined as follows. The bytes of the value are first converted into anint constantbits. Then:

  • Ifbits is0x7f800000, thefloat value will be positive infinity.

  • Ifbits is0xff800000, thefloat value will be negative infinity.

  • Ifbits is in the range0x7f800001 through0x7fffffff or in the range0xff800001 through0xffffffff, thefloat value will be NaN.

  • In all other cases, lets,e, andm be three values that might be computed frombits:

    int s = ((bits >> 31) == 0) ? 1 : -1;int e = ((bits >> 23) & 0xff);int m = (e == 0) ?          (bits & 0x7fffff) << 1 :          (bits & 0x7fffff) | 0x800000;

Then thefloat value equals the result of the mathematical expressions · m · 2e-150.

4.4.5. TheCONSTANT_Long_info andCONSTANT_Double_info Structures

TheCONSTANT_Long_info andCONSTANT_Double_info represent 8-byte numeric (long anddouble) constants:

CONSTANT_Long_info {    u1 tag;    u4 high_bytes;    u4 low_bytes;}CONSTANT_Double_info {    u1 tag;    u4 high_bytes;    u4 low_bytes;}

All 8-byte constants take up two entries in theconstant_pool table of theclass file. If aCONSTANT_Long_info orCONSTANT_Double_info structure is the entry at indexn in theconstant_pool table, then the next usable entry in the table is located at indexn+2. Theconstant_pool indexn+1 must be valid but is considered unusable.

In retrospect, making 8-byte constants take two constant pool entries was a poor choice.

The items of these structures are as follows:

tag

Thetag item of theCONSTANT_Long_info structure has the valueCONSTANT_Long (5).

Thetag item of theCONSTANT_Double_info structure has the valueCONSTANT_Double (6).

high_bytes, low_bytes

The unsignedhigh_bytes andlow_bytes items of theCONSTANT_Long_info structure together represent the value of thelong constant

((long) high_bytes << 32) + low_bytes

where the bytes of each ofhigh_bytes andlow_bytes are stored in big-endian (high byte first) order.

Thehigh_bytes andlow_bytes items of theCONSTANT_Double_info structure together represent thedouble value in IEEE 754 binary64 floating-point format (§2.3.2). The bytes of each item are stored in big-endian (high byte first) order.

The value represented by theCONSTANT_Double_info structure is determined as follows. Thehigh_bytes andlow_bytes items are converted into thelong constantbits, which is equal to

((long) high_bytes << 32) + low_bytes

Then:

  • Ifbits is0x7ff0000000000000L, thedouble value will be positive infinity.

  • Ifbits is0xfff0000000000000L, thedouble value will be negative infinity.

  • Ifbits is in the range0x7ff0000000000001L through0x7fffffffffffffffL or in the range0xfff0000000000001L through0xffffffffffffffffL, the double value will be NaN.

  • In all other cases, lets,e, andm be three values that might be computed frombits:

    int s = ((bits >> 63) == 0) ? 1 : -1;int e = (int)((bits >> 52) & 0x7ffL);long m = (e == 0) ?           (bits & 0xfffffffffffffL) << 1 :           (bits & 0xfffffffffffffL) | 0x10000000000000L;

Then the floating-point value equals thedouble value of the mathematical expressions · m · 2e-1075.

4.4.6. TheCONSTANT_NameAndType_info Structure

TheCONSTANT_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 theCONSTANT_NameAndType_info structure are as follows:

tag

Thetag item has the valueCONSTANT_NameAndType (12).

name_index

The value of thename_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing either a valid unqualified name denoting a field or method (§4.2.2), or the special method name<init> (§2.9.1).

descriptor_index

The value of thedescriptor_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing a valid field descriptor or method descriptor (§4.3.2,§4.3.3).

4.4.7. TheCONSTANT_Utf8_info Structure

TheCONSTANT_Utf8_info structure is used to represent constant string values:

CONSTANT_Utf8_info {    u1 tag;    u2 length;    u1 bytes[length];}

The items of theCONSTANT_Utf8_info structure are as follows:

tag

Thetag item has the valueCONSTANT_Utf8 (1).

length

The value of thelength item gives the number of bytes in thebytes array (not the length of the resulting string).

bytes[]

Thebytes array contains the bytes of the string.

No byte may have the value(byte)0.

No byte may lie in the range(byte)0xf0 to(byte)0xff.

String content is encoded in modified UTF-8. Modified UTF-8 strings are encoded so that code point sequences that contain only non-null ASCII characters can be represented using only 1 byte per code point, but all code points in the Unicode codespace can be represented. Modified UTF-8 strings are not null-terminated. The encoding is as follows:

  • Code points in the range '\u0001' to '\u007F' are represented by a single byte:

    Table 4.7. 

    0bits 6-0

    The 7 bits of data in the byte give the value of the code point represented.

  • The null code point ('\u0000') and code points in the range '\u0080' to '\u07FF' are represented by a pair of bytesx andy :

    Table 4.8. 

    x:

    Table 4.9. 

    110bits 10-6

    y:

    Table 4.10. 

    10bits 5-0


    The two bytes represent the code point with the value:

    ((x & 0x1f) << 6) + (y & 0x3f)
  • Code points in the range '\u0800' to '\uFFFF' are represented by 3 bytesx,y, andz :

    Table 4.11. 

    x:

    Table 4.12. 

    1110bits 15-12

    y:

    Table 4.13. 

    10bits 11-6

    z:

    Table 4.14. 

    10bits 5-0


    The three bytes represent the code point with the value:

    ((x & 0xf) << 12) + ((y & 0x3f) << 6) + (z & 0x3f)
  • Characters with code points above U+FFFF (so-calledsupplementary characters) are represented by separately encoding the two surrogate code units of their UTF-16 representation. Each of the surrogate code units is represented by three bytes. This means supplementary characters are represented by six bytes,u,v,w,x,y, andz :

    Table 4.15. 

    u:

    Table 4.16. 

    11101101

    v:

    Table 4.17. 

    1010(bits 20-16)-1

    w:

    Table 4.18. 

    10bits 15-10

    x:

    Table 4.19. 

    11101101

    y:

    Table 4.20. 

    1011bits 9-6

    z:

    Table 4.21. 

    10bits 5-0


    The six bytes represent the code point with the value:

    0x10000 + ((v & 0x0f) << 16) + ((w & 0x3f) << 10) +((y & 0x0f) << 6) + (z & 0x3f)

The bytes of multibyte characters are stored in theclass file in big-endian (high byte first) order.

There are two differences between this format and the "standard" UTF-8 format. First, the null character(char)0 is encoded using the 2-byte format rather than the 1-byte format, so that modified UTF-8 strings never have embedded nulls. Second, only the 1-byte, 2-byte, and 3-byte formats of standard UTF-8 are used. The Java Virtual Machine does not recognize the four-byte format of standard UTF-8; it uses its own two-times-three-byte format instead.

For more information regarding the standard UTF-8 format, see Section 3.9Unicode Encoding Forms ofThe Unicode Standard, Version 16.0.0.

4.4.8. TheCONSTANT_MethodHandle_info Structure

TheCONSTANT_MethodHandle_info structure is used to represent a method handle:

CONSTANT_MethodHandle_info {    u1 tag;    u1 reference_kind;    u2 reference_index;}

The items of theCONSTANT_MethodHandle_info structure are the following:

tag

Thetag item has the valueCONSTANT_MethodHandle (15).

reference_kind

The value of thereference_kind item must be in the range 1 to 9. The value denotes thekind of this method handle, which characterizes its bytecode behavior (§5.4.3.5).

reference_index

The value of thereference_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be as follows:

  • If the value of thereference_kind item is 1 (REF_getField), 2 (REF_getStatic), 3 (REF_putField), or 4 (REF_putStatic), then theconstant_pool entry at that index must be aCONSTANT_Fieldref_info structure (§4.4.2) representing a field for which a method handle is to be created.

  • If the value of thereference_kind item is 5 (REF_invokeVirtual) or 8 (REF_newInvokeSpecial), then theconstant_pool entry at that index must be aCONSTANT_Methodref_info structure (§4.4.2) representing a class's method or constructor (§2.9.1) for which a method handle is to be created.

  • If the value of thereference_kind item is 6 (REF_invokeStatic) or 7 (REF_invokeSpecial), then if theclass file version number is less than 52.0, theconstant_pool entry at that index must be aCONSTANT_Methodref_info structure representing a class's method for which a method handle is to be created; if theclass file version number is 52.0 or above, theconstant_pool entry at that index must be either aCONSTANT_Methodref_info structure or aCONSTANT_InterfaceMethodref_info structure (§4.4.2) representing a class's or interface's method for which a method handle is to be created.

  • If the value of thereference_kind item is 9 (REF_invokeInterface), then theconstant_pool entry at that index must be aCONSTANT_InterfaceMethodref_info structure representing an interface's method for which a method handle is to be created.

If the value of thereference_kind item is 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial), or 9 (REF_invokeInterface), the name of the method represented by aCONSTANT_Methodref_info structure or aCONSTANT_InterfaceMethodref_info structure must not be<init> or<clinit>.

If the value is 8 (REF_newInvokeSpecial), the name of the method represented by aCONSTANT_Methodref_info structure must be<init>.

4.4.9. TheCONSTANT_MethodType_info Structure

TheCONSTANT_MethodType_info structure is used to represent a method type:

CONSTANT_MethodType_info {    u1 tag;    u2 descriptor_index;}

The items of theCONSTANT_MethodType_info structure are as follows:

tag

Thetag item has the valueCONSTANT_MethodType (16).

descriptor_index

The value of thedescriptor_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing a method descriptor (§4.3.3).

4.4.10. TheCONSTANT_Dynamic_info andCONSTANT_InvokeDynamic_info Structures

Most structures in theconstant_pool table represent entities directly, by combining names, descriptors, and values recorded statically in the table. In contrast, theCONSTANT_Dynamic_info andCONSTANT_InvokeDynamic_info structures represent entities indirectly, by pointing to code which computes an entity dynamically. The code, called abootstrap method, is invoked by the Java Virtual Machine during resolution of symbolic references derived from these structures (§5.1,§5.4.3.6). Each structure specifies a bootstrap method as well as an auxiliary name and type that characterize the entity to be computed. In more detail:

  • TheCONSTANT_Dynamic_info structure is used to represent adynamically-computed constant, an arbitrary value that is produced by invocation of a bootstrap method in the course of anldc instruction (§ldc), among others. The auxiliary type specified by the structure constrains the type of the dynamically-computed constant.

  • TheCONSTANT_InvokeDynamic_info structure is used to represent adynamically-computed call site, an instance ofjava.lang.invoke.CallSite that is produced by invocation of a bootstrap method in the course of aninvokedynamic instruction (§invokedynamic). The auxiliary type specified by the structure constrains the method type of the dynamically-computed call site.

CONSTANT_Dynamic_info {    u1 tag;    u2 bootstrap_method_attr_index;    u2 name_and_type_index;}CONSTANT_InvokeDynamic_info {    u1 tag;    u2 bootstrap_method_attr_index;    u2 name_and_type_index;}

The items of these structures are as follows:

tag

Thetag item of aCONSTANT_Dynamic_info structure has the valueCONSTANT_Dynamic (17).

Thetag item of aCONSTANT_InvokeDynamic_info structure has the valueCONSTANT_InvokeDynamic (18).

bootstrap_method_attr_index

The value of thebootstrap_method_attr_index item must be a valid index into thebootstrap_methods array of the bootstrap method table of thisclass file (§4.7.23).

CONSTANT_Dynamic_info structures are unique in that they are syntactically allowed to refer to themselves via the bootstrap method table. Rather than mandating that such cycles are detected when classes are loaded (a potentially expensive check), we permit cycles initially but mandate a failure at resolution (§5.4.3.6).

name_and_type_index

The value of thename_and_type_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_NameAndType_info structure (§4.4.6). Thisconstant_pool entry indicates a name and descriptor.

In aCONSTANT_Dynamic_info structure, the indicated descriptor must be a field descriptor (§4.3.2).

In aCONSTANT_InvokeDynamic_info structure, the indicated descriptor must be a method descriptor (§4.3.3).

4.4.11. TheCONSTANT_Module_info Structure

TheCONSTANT_Module_info structure is used to represent a module:

CONSTANT_Module_info {    u1 tag;    u2 name_index;}

The items of theCONSTANT_Module_info structure are as follows:

tag

Thetag item has the valueCONSTANT_Module (19).

name_index

The value of thename_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing a valid module name (§4.2.3).

ACONSTANT_Module_info structure is permitted only in the constant pool of aclass file that declares a module, that is, aClassFile structure where theaccess_flags item has theACC_MODULE flag set. In all otherclass files, aCONSTANT_Module_info structure is illegal.

4.4.12. TheCONSTANT_Package_info Structure

TheCONSTANT_Package_info structure is used to represent a package exported or opened by a module:

CONSTANT_Package_info {    u1 tag;    u2 name_index;}

The items of theCONSTANT_Package_info structure are as follows:

tag

Thetag item has the valueCONSTANT_Package (20).

name_index

The value of thename_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing a valid package name encoded in internal form (§4.2.3).

ACONSTANT_Package_info structure is permitted only in the constant pool of aclass file that declares a module, that is, aClassFile structure where theaccess_flags item has theACC_MODULE flag set. In all otherclass files, aCONSTANT_Package_info structure is illegal.

4.5. Fields

Each field is described by afield_info structure.

No two fields in oneclass 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 thefield_info structure are as follows:

access_flags

The value of theaccess_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 inTable 4.5-A.

Table 4.5-A. Field access and property flags

Flag NameValueInterpretation
ACC_PUBLIC0x0001Declaredpublic; may be accessed from outside its package.
ACC_PRIVATE0x0002

Declaredprivate; accessible only within the defining class and other classes belonging to the same nest (§5.4.4).

ACC_PROTECTED0x0004Declaredprotected; may be accessed within subclasses.
ACC_STATIC0x0008Declaredstatic.
ACC_FINAL0x0010Declaredfinal; never directly assigned to after object construction (JLS §17.5).
ACC_VOLATILE0x0040Declaredvolatile; cannot be cached.
ACC_TRANSIENT0x0080Declaredtransient; not written or read by a persistent object manager.
ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
ACC_ENUM0x4000Declared as an element of anenum class.

Fields of classes may set any of the flags inTable 4.5-A. However, each field of a class may have at most one of itsACC_PUBLIC,ACC_PRIVATE, andACC_PROTECTED flags set (JLS §8.3.1), and must not have both itsACC_FINAL andACC_VOLATILE flags set (JLS §8.3.1.4).

Fields of interfaces must have theirACC_PUBLIC,ACC_STATIC, andACC_FINAL flags set; they may have theirACC_SYNTHETIC flag set and must not have any of the other flags inTable 4.5-A set (JLS §9.3).

TheACC_SYNTHETIC flag indicates that this field was generated by a compiler and does not appear in source code.

TheACC_ENUM flag indicates that this field is used to hold an element of an enum class (JLS §8.9).

All bits of theaccess_flags item not assigned inTable 4.5-A are reserved for future use. They should be set to zero in generatedclass files and should be ignored by Java Virtual Machine implementations.

name_index

The value of thename_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) which represents a valid unqualified name denoting a field (§4.2.2).

descriptor_index

The value of thedescriptor_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) which represents a valid field descriptor (§4.3.2).

attributes_count

The value of theattributes_count item indicates the number of additional attributes of this field.

attributes[]

Each value of theattributes table must be anattribute_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 theattributes table of afield_info structure are listed inTable 4.7-C.

The rules concerning attributes defined to appear in theattributes table of afield_info structure are given in§4.7.

The rules concerning non-predefined attributes in theattributes table of afield_info structure are given in§4.7.1.

4.6. Methods

Each method, including each instance initialization method (§2.9.1) and the class or interface initialization method (§2.9.2), is described by amethod_info structure.

No two methods in oneclass 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 themethod_info structure are as follows:

access_flags

The value of theaccess_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 inTable 4.6-A.

Table 4.6-A. Method access and property flags

Flag NameValueInterpretation
ACC_PUBLIC0x0001Declaredpublic; may be accessed from outside its package.
ACC_PRIVATE0x0002

Declaredprivate; accessible only within the defining class and other classes belonging to the same nest (§5.4.4).

ACC_PROTECTED0x0004Declaredprotected; may be accessed within subclasses.
ACC_STATIC0x0008Declaredstatic.
ACC_FINAL0x0010Declaredfinal; must not be overridden (§5.4.5).
ACC_SYNCHRONIZED0x0020Declaredsynchronized; invocation is wrapped by a monitor use.
ACC_BRIDGE0x0040A bridge method, generated by the compiler.
ACC_VARARGS0x0080Declared with variable number of arguments.
ACC_NATIVE0x0100Declarednative; implemented in a language other than the Java programming language.
ACC_ABSTRACT0x0400Declaredabstract; no implementation is provided.
ACC_STRICT0x0800

In aclass file whose major version number is at least 46 and at most 60: Declaredstrictfp.

ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.

The value 0x0800 is interpreted as theACC_STRICT flag only in aclass file whose major version number is at least 46 and at most 60. For methods in such aclass file, the rules below determine whether theACC_STRICT flag may be set in combination with other flags. (Setting theACC_STRICT flag constrained a method's floating-point instructions in Java SE 1.2 through 16 (§2.8).) For methods in aclass file whose major version number is less than 46 or greater than 60, the value 0x0800 is not interpreted as theACC_STRICT flag, but rather is unassigned; it is not meaningful to "set theACC_STRICT flag" in such aclass file.

Methods of classes may have any of the flags inTable 4.6-A set. However, each method of a class may have at most one of itsACC_PUBLIC,ACC_PRIVATE, andACC_PROTECTED flags set (JLS §8.4.3).

Methods of interfaces may have any of the flags inTable 4.6-A set exceptACC_PROTECTED,ACC_FINAL,ACC_SYNCHRONIZED, andACC_NATIVE (JLS §9.4). In aclass file whose version number is less than 52.0, each method of an interface must have itsACC_PUBLIC andACC_ABSTRACT flags set; in aclass file whose version number is 52.0 or above, each method of an interface must have exactly one of itsACC_PUBLIC andACC_PRIVATE flags set.

If a method of a class or interface has itsACC_ABSTRACT flag set, it must not have any of itsACC_PRIVATE,ACC_STATIC,ACC_FINAL,ACC_SYNCHRONIZED, orACC_NATIVE flags set, nor (in aclass file whose major version number is at least 46 and at most 60) have itsACC_STRICT flag set.

An instance initialization method (§2.9.1) may have at most one of itsACC_PUBLIC,ACC_PRIVATE, andACC_PROTECTED flags set, and may also have itsACC_VARARGS andACC_SYNTHETIC flags set, and may also (in aclass file whose major version number is at least 46 and at most 60) have itsACC_STRICT flag set, but must not have any of the other flags inTable 4.6-A set.

In aclass file whose version number is 51.0 or above, a method whose name is<clinit> must have itsACC_STATIC flag set.

A class or interface initialization method (§2.9.2) is called implicitly by the Java Virtual Machine. The value of itsaccess_flags item is ignored except for the setting of theACC_STATIC flag and (in aclass file whose major version number is at least 46 and at most 60) theACC_STRICT flag, and the method is exempt from the preceding rules about legal combinations of flags.

TheACC_BRIDGE flag is used to indicate a bridge method generated by a compiler for the Java programming language.

TheACC_VARARGS flag indicates that this method takes a variable number of arguments at the source code level. A method declared to take a variable number of arguments must be compiled with theACC_VARARGS flag set to 1. All other methods must be compiled with theACC_VARARGS flag set to 0.

TheACC_SYNTHETIC flag indicates that this method was generated by a compiler and does not appear in source code, unless it is one of the methods named in§4.7.8.

All bits of theaccess_flags item not assigned inTable 4.6-A are reserved for future use. (This includes the bit corresponding to 0x0800 in aclass file whose major version number is less than 46 or greater than 60.) They should be set to zero in generatedclass files and should be ignored by Java Virtual Machine implementations.

name_index

The value of thename_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing either a valid unqualified name denoting a method (§4.2.2), or (if this method is in a class rather than an interface) the special method name<init>, or the special method name<clinit>.

descriptor_index

The value of thedescriptor_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure representing a valid method descriptor (§4.3.3). Furthermore:

  • If this method is in a class rather than an interface, and the name of the method is<init>, then the descriptor must denote avoid method.

  • If the name of the method is<clinit>, then the descriptor must denote avoid method, and, in aclass file whose version number is 51.0 or above, a method that takes no arguments.

A future edition of this specification may require that the last parameter descriptor of the method descriptor is an array type if theACC_VARARGS flag is set in theaccess_flags item.

attributes_count

The value of theattributes_count item indicates the number of additional attributes of this method.

attributes[]

Each value of theattributes table must be anattribute_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 theattributes table of amethod_info structure are listed inTable 4.7-C.

The rules concerning attributes defined to appear in theattributes table of amethod_info structure are given in§4.7.

The rules concerning non-predefined attributes in theattributes table of amethod_info structure are given in§4.7.1.

4.7. Attributes

Attributes are used in theClassFile,field_info,method_info,Code_attribute, andrecord_component_info structures of theclass file format (§4.1,§4.5,§4.6,§4.7.3,§4.7.30).

All attributes have the following general format:

attribute_info {    u2 attribute_name_index;    u4 attribute_length;    u1 info[attribute_length];}

For all attributes, theattribute_name_index item must be a valid unsigned 16-bit index into the constant pool of the class. Theconstant_pool entry atattribute_name_index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the name of the attribute. The value of theattribute_length item indicates the length of the subsequent information in bytes. The length does not include the initial six bytes that contain theattribute_name_index andattribute_length items.

30 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 shown with the first version of theclass file format in which it was defined. Also shown is the version of the Java SE Platform which introduced that version of theclass file format (§4.1).

  • Table 4.7-B is ordered by the first version of theclass file format in which each attribute was defined.

  • Table 4.7-C is ordered by the location in aclass file where each attribute is defined to appear.

Within the context of their use in this specification, that is, in theattributes tables of theclass file structures in which they appear, the names of these predefined attributes are reserved.

Any conditions on the presence of a predefined attribute in anattributes 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 anattributes table.

The predefined attributes are categorized into three groups according to their purpose:

  1. Seven attributes are critical to correct interpretation of theclass file by the Java Virtual Machine:

    • ConstantValue

    • Code

    • StackMapTable

    • BootstrapMethods

    • NestHost

    • NestMembers

    • PermittedSubclasses

    In aclass file whose version number isv, each of these attributes must be recognized and correctly read by an implementation of the Java Virtual Machine if the implementation supports versionv of theclass file format, and the attribute was first defined in versionv or earlier of theclass file format, and the attribute appears in a location where it is defined to appear.

  2. Ten attributes are not critical to correct interpretation of theclass file by the Java Virtual Machine, but are either critical to correct interpretation of theclass file by the class libraries of the Java SE Platform, or are useful for tools (in which case the section that specifies an attribute describes it as "optional"):

    • Exceptions

    • InnerClasses

    • EnclosingMethod

    • Synthetic

    • Signature

    • Record

    • SourceFile

    • LineNumberTable

    • LocalVariableTable

    • LocalVariableTypeTable

    In aclass file whose version number isv, each of these attributes must be recognized and correctly read by an implementation of the Java Virtual Machine if the implementation supports versionv of theclass file format, and the attribute was first defined in versionv or earlier of theclass file format, and the attribute appears in a location where it is defined to appear.

  3. Thirteen attributes are not critical to correct interpretation of theclass file by the Java Virtual Machine, but contain metadata about theclass file that is either exposed by the class libraries of the Java SE Platform, or made available by tools (in which case the section that specifies an attribute describes it as "optional"):

    • SourceDebugExtension

    • Deprecated

    • RuntimeVisibleAnnotations

    • RuntimeInvisibleAnnotations

    • RuntimeVisibleParameterAnnotations

    • RuntimeInvisibleParameterAnnotations

    • RuntimeVisibleTypeAnnotations

    • RuntimeInvisibleTypeAnnotations

    • AnnotationDefault

    • MethodParameters

    • Module

    • ModulePackages

    • ModuleMainClass

    An implementation of the Java Virtual Machine may use the information that these attributes contain, or otherwise must silently ignore these attributes.

Table 4.7-A. Predefinedclass file attributes (by section)

AttributeSectionclass fileJava SE
ConstantValue§4.7.245.31.0.2
Code§4.7.345.31.0.2
StackMapTable§4.7.450.06
Exceptions§4.7.545.31.0.2
InnerClasses§4.7.645.31.1
EnclosingMethod§4.7.749.05.0
Synthetic§4.7.845.31.1
Signature§4.7.949.05.0
SourceFile§4.7.1045.31.0.2
SourceDebugExtension§4.7.1149.05.0
LineNumberTable§4.7.1245.31.0.2
LocalVariableTable§4.7.1345.31.0.2
LocalVariableTypeTable§4.7.1449.05.0
Deprecated§4.7.1545.31.1
RuntimeVisibleAnnotations§4.7.1649.05.0
RuntimeInvisibleAnnotations§4.7.1749.05.0
RuntimeVisibleParameterAnnotations§4.7.1849.05.0
RuntimeInvisibleParameterAnnotations§4.7.1949.05.0
RuntimeVisibleTypeAnnotations§4.7.2052.08
RuntimeInvisibleTypeAnnotations§4.7.2152.08
AnnotationDefault§4.7.2249.05.0
BootstrapMethods§4.7.2351.07
MethodParameters§4.7.2452.08

Module

§4.7.2553.09

ModulePackages

§4.7.2653.09

ModuleMainClass

§4.7.2753.09

NestHost

§4.7.2855.011

NestMembers

§4.7.2955.011

Record

§4.7.3060.016

PermittedSubclasses

§4.7.3161.017

Table 4.7-B. Predefinedclass file attributes (byclass file format)

Attributeclass fileJava SESection
ConstantValue45.31.0.2§4.7.2
Code45.31.0.2§4.7.3
Exceptions45.31.0.2§4.7.5
SourceFile45.31.0.2§4.7.10
LineNumberTable45.31.0.2§4.7.12
LocalVariableTable45.31.0.2§4.7.13
InnerClasses45.31.1§4.7.6
Synthetic45.31.1§4.7.8
Deprecated45.31.1§4.7.15
EnclosingMethod49.05.0§4.7.7
Signature49.05.0§4.7.9
SourceDebugExtension49.05.0§4.7.11
LocalVariableTypeTable49.05.0§4.7.14
RuntimeVisibleAnnotations49.05.0§4.7.16
RuntimeInvisibleAnnotations49.05.0§4.7.17
RuntimeVisibleParameterAnnotations49.05.0§4.7.18
RuntimeInvisibleParameterAnnotations49.05.0§4.7.19
AnnotationDefault49.05.0§4.7.22
StackMapTable50.06§4.7.4
BootstrapMethods51.07§4.7.23
RuntimeVisibleTypeAnnotations52.08§4.7.20
RuntimeInvisibleTypeAnnotations52.08§4.7.21
MethodParameters52.08§4.7.24

Module

53.09§4.7.25

ModulePackages

53.09§4.7.26

ModuleMainClass

53.09§4.7.27

NestHost

55.011§4.7.28

NestMembers

55.011§4.7.29

Record

60.016§4.7.30

PermittedSubclasses

61.017§4.7.31

Table 4.7-C. Predefinedclass file attributes (by location)

AttributeLocationclass file
SourceFileClassFile45.3
InnerClassesClassFile45.3
EnclosingMethodClassFile49.0
SourceDebugExtensionClassFile49.0
BootstrapMethodsClassFile51.0

Module,ModulePackages,ModuleMainClass

ClassFile53.0

NestHost,NestMembers

ClassFile55.0

Record

ClassFile60.0

PermittedSubclasses

ClassFile61.0
ConstantValuefield_info45.3
Codemethod_info45.3
Exceptionsmethod_info45.3
RuntimeVisibleParameterAnnotations,RuntimeInvisibleParameterAnnotationsmethod_info49.0
AnnotationDefaultmethod_info49.0
MethodParametersmethod_info52.0

Table 4.7-C (cont.). Predefinedclass file attributes (by location)

AttributeLocationclass file
SyntheticClassFile,field_info,method_info45.3
DeprecatedClassFile,field_info,method_info45.3
Signature

ClassFile,field_info,method_info,record_component_info

49.0
RuntimeVisibleAnnotations,RuntimeInvisibleAnnotations

ClassFile,field_info,method_info,record_component_info

49.0
LineNumberTableCode45.3
LocalVariableTableCode45.3
LocalVariableTypeTableCode49.0
StackMapTableCode50.0
RuntimeVisibleTypeAnnotations,RuntimeInvisibleTypeAnnotations

ClassFile,field_info,method_info,Code,record_component_info

52.0

4.7.1. Defining and Naming New Attributes

Compilers are permitted to define and emitclass files containing new attributes in theattributes tables ofclass file structures,field_info structures,method_info structures, andCode attributes (§4.7.3). Java Virtual Machine implementations are permitted to recognize and use new attributes found in theseattributes tables. However, any attribute not defined as part of this specification must not affect the semantics of theclass file. Java Virtual Machine implementations are required to silently ignore attributes they do not recognize.

For instance, defining a new attribute to support vendor-specific debugging is permitted. Because Java Virtual Machine implementations are required to ignore attributes they do not recognize,class files intended for that particular Java Virtual Machine implementation will be usable by other implementations even if those implementations cannot make use of the additional debugging information that theclass files contain.

Java Virtual Machine implementations are specifically prohibited from throwing an exception or otherwise refusing to useclass files simply because of the presence of some new attribute. Of course, tools operating onclass files may not run correctly if givenclass files that do not contain all the attributes they require.

Two attributes that are intended to be distinct, but that happen to use the same attribute name and are of the same length, will conflict on implementations that recognize either attribute. Attributes defined other than in this specification should have names chosen according to the package naming convention described inThe Java Language Specification, Java SE 24 Edition (JLS §6.1).

Future versions of this specification may define additional attributes.

4.7.2. TheConstantValue Attribute

TheConstantValue attribute is a fixed-length attribute in theattributes table of afield_info structure (§4.5). AConstantValue attribute represents the value of a constant expression (JLS §15.28), and is used as follows:

  • If theACC_STATIC flag in theaccess_flags item of thefield_info structure is set, then the field represented by thefield_info structure is assigned the value represented by itsConstantValue attribute as part of the initialization of the class or interface declaring the field (§5.5). This occurs prior to the invocation of the class or interface initialization method of that class or interface (§2.9.2).

  • Otherwise, the Java Virtual Machine must silently ignore the attribute.

There may be at most oneConstantValue attribute in theattributes table of afield_info structure.

TheConstantValue attribute has the following format:

ConstantValue_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 constantvalue_index;}

The items of theConstantValue_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "ConstantValue".

attribute_length

The value of theattribute_length item must be two.

constantvalue_index

The value of theconstantvalue_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index gives the value represented by this attribute. Theconstant_pool entry must be of a type appropriate to the field, as specified inTable 4.7.2-A.

Table 4.7.2-A. Constant value attribute types

Field TypeEntry Type
int,short,char,byte,booleanCONSTANT_Integer
floatCONSTANT_Float
longCONSTANT_Long
doubleCONSTANT_Double
StringCONSTANT_String

4.7.3. TheCode Attribute

TheCode attribute is a variable-length attribute in theattributes table of amethod_info structure (§4.6). ACode attribute contains the Java Virtual Machine instructions and auxiliary information for a method, including an instance initialization method and a class or interface initialization method (§2.9.1,§2.9.2).

If the method is eithernative orabstract, and is not a class or interface initialization method, then itsmethod_info structure must not have aCode attribute in itsattributes table. Otherwise, itsmethod_info structure must have exactly oneCode attribute in itsattributes table.

TheCode attribute has the following format:

Code_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 max_stack;    u2 max_locals;    u4 code_length;    u1 code[code_length];    u2 exception_table_length;    {   u2 start_pc;        u2 end_pc;        u2 handler_pc;        u2 catch_type;    } exception_table[exception_table_length];    u2 attributes_count;    attribute_info attributes[attributes_count];}

The items of theCode_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "Code".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

max_stack

The value of themax_stack item gives the maximum depth of the operand stack of this method (§2.6.2) at any point during execution of the method.

max_locals

The value of themax_locals item gives the number of local variables in the local variable array allocated upon invocation of this method (§2.6.1), including the local variables used to pass parameters to the method on its invocation.

The greatest local variable index for a value of typelong ordouble ismax_locals - 2. The greatest local variable index for a value of any other type ismax_locals - 1.

code_length

The value of thecode_length item gives the number of bytes in thecode array for this method.

The value ofcode_length must be greater than zero (as thecode array must not be empty) and less than 65536.

code[]

Thecode array gives the actual bytes of Java Virtual Machine code that implement the method.

When thecode array is read into memory on a byte-addressable machine, if the first byte of the array is aligned on a 4-byte boundary, thetableswitch andlookupswitch 32-bit offsets will be 4-byte aligned. (Refer to the descriptions of those instructions for more information on the consequences ofcode array alignment.)

The detailed constraints on the contents of thecode array are extensive and are given in a separate section (§4.9).

exception_table_length

The value of theexception_table_length item gives the number of entries in theexception_table array.

exception_table[]

Each entry in theexception_table array describes one exception handler in thecode array. The order of the handlers in theexception_table array is significant (§2.10).

Eachexception_table entry contains the following four items:

start_pc, end_pc

The values of the two itemsstart_pc andend_pc indicate the ranges in thecode array at which the exception handler is active. The value ofstart_pc must be a valid index into thecode array of the opcode of an instruction. The value ofend_pc either must be a valid index into thecode array of the opcode of an instruction or must be equal tocode_length, the length of thecode array. The value ofstart_pc must be less than the value ofend_pc.

Thestart_pc is inclusive andend_pc is exclusive; that is, the exception handler must be active while the program counter is within the interval [start_pc,end_pc).

The fact thatend_pc is exclusive is a historical mistake in the design of the Java Virtual Machine: if the Java Virtual Machine code for a method is exactly 65535 bytes long and ends with an instruction that is 1 byte long, then that instruction cannot be protected by an exception handler. A compiler writer can work around this bug by limiting the maximum size of the generated Java Virtual Machine code for any method, instance initialization method, or static initializer (the size of any code array) to 65534 bytes.

handler_pc

The value of thehandler_pc item indicates the start of the exception handler. The value of the item must be a valid index into thecode array and must be the index of the opcode of an instruction.

catch_type

If the value of thecatch_type item is nonzero, it must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure (§4.4.1) representing a class of exceptions that this exception handler is designated to catch. The exception handler will be called only if the thrown exception is an instance of the given class or one of its subclasses.

The verifier checks that the class isThrowable or a subclass ofThrowable (§4.9.2).

If the value of thecatch_type item is zero, this exception handler is called for all exceptions.

This is used to implementfinally (§3.13).

attributes_count

The value of theattributes_count item indicates the number of attributes of theCode attribute.

attributes[]

Each value of theattributes table must be anattribute_info structure (§4.7).

ACode attribute can have any number of optional attributes associated with it.

The attributes defined by this specification as appearing in theattributes table of aCode attribute are listed inTable 4.7-C.

The rules concerning attributes defined to appear in theattributes table of aCode attribute are given in§4.7.

The rules concerning non-predefined attributes in theattributes table of aCode attribute are given in§4.7.1.

4.7.4. TheStackMapTable Attribute

TheStackMapTable attribute is a variable-length attribute in theattributes table of aCode attribute (§4.7.3). AStackMapTable attribute is used during the process of verification by type checking (§4.10.1).

There may be at most oneStackMapTable attribute in theattributes table of aCode attribute.

In aclass file whose version number is 50.0 or above, if a method'sCode attribute does not have aStackMapTable attribute, it has animplicit stack map attribute (§4.10.1). This implicit stack map attribute is equivalent to aStackMapTable attribute withnumber_of_entries equal to zero.

TheStackMapTable attribute has the following format:

StackMapTable_attribute {    u2              attribute_name_index;    u4              attribute_length;    u2              number_of_entries;    stack_map_frame entries[number_of_entries];}

The items of theStackMapTable_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "StackMapTable".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

number_of_entries

The value of thenumber_of_entries item gives the number ofstack_map_frame entries in theentries table.

entries[]

Each entry in theentries table describes one stack map frame of the method. The order of the stack map frames in theentries table is significant.

Astack map frame specifies (either explicitly or implicitly) the bytecode offset at which it applies, and the verification types of local variables and operand stack entries for that offset.

Each stack map frame described in theentries table relies on the previous frame for some of its semantics. The first stack map frame of a method is implicit, and computed from the method descriptor by the type checker (§4.10.1.6). Thestack_map_frame structure atentries[0] therefore describes the second stack map frame of the method.

Thebytecode offset at which a stack map frame applies is calculated by taking the valueoffset_delta specified in the frame (either explicitly or implicitly), and addingoffset_delta + 1 to the bytecode offset of the previous frame, unless the previous frame is the initial frame of the method. In that case, the bytecode offset at which the stack map frame applies is the valueoffset_delta specified in the frame.

By using an offset delta rather than storing the actual bytecode offset, we ensure, by definition, that stack map frames are in the correctly sorted order. Furthermore, by consistently using the formulaoffset_delta + 1 for all explicit frames (as opposed to the implicit first frame), we guarantee the absence of duplicates.

We say that an instruction in the bytecode has acorresponding stack map frame if the instruction starts at offseti in thecode array of aCode attribute, and theCode attribute has aStackMapTable attribute whoseentries array contains a stack map frame that applies at bytecode offseti.

Averification type specifies the type of either one or two locations, where alocation is either a single local variable or a single operand stack entry. A verification type is represented by a discriminated union,verification_type_info, that consists of a one-byte tag, indicating which item of the union is in use, followed by zero or more bytes, giving more information about the tag.

union verification_type_info {    Top_variable_info;    Integer_variable_info;    Float_variable_info;    Long_variable_info;    Double_variable_info;    Null_variable_info;    UninitializedThis_variable_info;    Object_variable_info;    Uninitialized_variable_info;}

A verification type that specifies one location in the local variable array or in the operand stack is represented by the following items of theverification_type_info union:

  • TheTop_variable_info item indicates that the local variable has the verification typetop.

    Top_variable_info {    u1 tag = ITEM_Top; /* 0 */}
  • TheInteger_variable_info item indicates that the location has the verification typeint.

    Integer_variable_info {    u1 tag = ITEM_Integer; /* 1 */}
  • TheFloat_variable_info item indicates that the location has the verification typefloat.

    Float_variable_info {    u1 tag = ITEM_Float; /* 2 */}
  • TheNull_variable_info type indicates that the location has the verification typenull.

    Null_variable_info {    u1 tag = ITEM_Null; /* 5 */}
  • TheUninitializedThis_variable_info item indicates that the location has the verification typeuninitializedThis.

    UninitializedThis_variable_info {    u1 tag = ITEM_UninitializedThis; /* 6 */}
  • TheObject_variable_info item indicates that the location has the verification type which is the class represented by theCONSTANT_Class_info structure (§4.4.1) found in theconstant_pool table at the index given bycpool_index.

    Object_variable_info {    u1 tag = ITEM_Object; /* 7 */    u2 cpool_index;}
  • TheUninitialized_variable_info item indicates that the location has the verification typeuninitialized(Offset). TheOffset item indicates the offset, in thecode array of theCode attribute that contains thisStackMapTable attribute, of thenew instruction (§new) that created the object being stored in the location.

    Uninitialized_variable_info {    u1 tag = ITEM_Uninitialized; /* 8 */    u2 offset;}

A verification type that specifies two locations in the local variable array or in the operand stack is represented by the following items of theverification_type_info union:

  • TheLong_variable_info item indicates that the first of two locations has the verification typelong.

    Long_variable_info {    u1 tag = ITEM_Long; /* 4 */}
  • TheDouble_variable_info item indicates that the first of two locations has the verification typedouble.

    Double_variable_info {    u1 tag = ITEM_Double; /* 3 */}
  • TheLong_variable_info andDouble_variable_info items indicate the verification type of the second of two locations as follows:

    • If the first of the two locations is a local variable, then:

      • It must not be the local variable with the highest index.

      • The next higher numbered local variable has the verification typetop.

    • If the first of the two locations is an operand stack entry, then:

      • It must not be the topmost location of the operand stack.

      • The next location closer to the top of the operand stack has the verification typetop.

A stack map frame is represented by a discriminated union,stack_map_frame, which consists of a one-byte tag, indicating which item of the union is in use, followed by zero or more bytes, giving more information about the tag.

union stack_map_frame {    same_frame;    same_locals_1_stack_item_frame;    same_locals_1_stack_item_frame_extended;    chop_frame;    same_frame_extended;    append_frame;    full_frame;}

The tag indicates theframe type of the stack map frame:

  • The frame typesame_frame is represented by tags in the range [0-63]. This frame type indicates that the frame has exactly the same local variables as the previous frame and that the operand stack is empty. Theoffset_delta value for the frame is the value of the tag item,frame_type.

    same_frame {    u1 frame_type = SAME; /* 0-63 */}
  • The frame typesame_locals_1_stack_item_frame is represented by tags in the range [64, 127]. This frame type indicates that the frame has exactly the same local variables as the previous frame and that the operand stack has one entry. Theoffset_delta value for the frame is given by the formulaframe_type - 64. The verification type of the one stack entry appears after the frame type.

    same_locals_1_stack_item_frame {    u1 frame_type = SAME_LOCALS_1_STACK_ITEM; /* 64-127 */    verification_type_info stack[1];}
  • Tags in the range [128-246] are reserved for future use.

  • The frame typesame_locals_1_stack_item_frame_extended is represented by the tag 247. This frame type indicates that the frame has exactly the same local variables as the previous frame and that the operand stack has one entry. Theoffset_delta value for the frame is given explicitly, unlike in the frame typesame_locals_1_stack_item_frame. The verification type of the one stack entry appears afteroffset_delta.

    same_locals_1_stack_item_frame_extended {    u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; /* 247 */    u2 offset_delta;    verification_type_info stack[1];}
  • The frame typechop_frame is represented by tags in the range [248-250]. This frame type indicates that the frame has the same local variables as the previous frame except that the lastk local variables are absent, and that the operand stack is empty. The value ofk is given by the formula251 - frame_type. Theoffset_delta value for the frame is given explicitly.

    chop_frame {    u1 frame_type = CHOP; /* 248-250 */    u2 offset_delta;}

    Assume the verification types of local variables in the previous frame are given bylocals, an array structured as in thefull_frame frame type. Iflocals[M-1] in the previous frame represented local variableX andlocals[M] represented local variableY, then the effect of removing one local variable is thatlocals[M-1] in the new frame represents local variableX andlocals[M] is undefined.

    It is an error ifk is larger than the number of local variables inlocals for the previous frame, that is, if the number of local variables in the new frame would be less than zero.

  • The frame typesame_frame_extended is represented by the tag 251. This frame type indicates that the frame has exactly the same local variables as the previous frame and that the operand stack is empty. Theoffset_delta value for the frame is given explicitly, unlike in the frame typesame_frame.

    same_frame_extended {    u1 frame_type = SAME_FRAME_EXTENDED; /* 251 */    u2 offset_delta;}
  • The frame typeappend_frame is represented by tags in the range [252-254]. This frame type indicates that the frame has the same locals as the previous frame except thatk additional locals are defined, and that the operand stack is empty. The value ofk is given by the formulaframe_type - 251. Theoffset_delta value for the frame is given explicitly.

    append_frame {    u1 frame_type = APPEND; /* 252-254 */    u2 offset_delta;    verification_type_info locals[frame_type - 251];}

    The 0th entry inlocals represents the verification type of the first additional local variable. Iflocals[M] represents local variableN, then:

    • locals[M+1] represents local variableN+1 iflocals[M] is one ofTop_variable_info,Integer_variable_info,Float_variable_info,Null_variable_info,UninitializedThis_variable_info,Object_variable_info, orUninitialized_variable_info; and

    • locals[M+1] represents local variableN+2 iflocals[M] is eitherLong_variable_info orDouble_variable_info.

    It is an error if, for any indexi,locals[i] represents a local variable whose index is greater than the maximum number of local variables for the method.

  • The frame typefull_frame is represented by the tag 255. Theoffset_delta value for the frame is given explicitly.

    full_frame {    u1 frame_type = FULL_FRAME; /* 255 */    u2 offset_delta;    u2 number_of_locals;    verification_type_info locals[number_of_locals];    u2 number_of_stack_items;    verification_type_info stack[number_of_stack_items];}

    The 0th entry inlocals represents the verification type of local variable 0. Iflocals[M] represents local variableN, then:

    • locals[M+1] represents local variableN+1 iflocals[M] is one ofTop_variable_info,Integer_variable_info,Float_variable_info,Null_variable_info,UninitializedThis_variable_info,Object_variable_info, orUninitialized_variable_info; and

    • locals[M+1] represents local variableN+2 iflocals[M] is eitherLong_variable_info orDouble_variable_info.

    It is an error if, for any indexi,locals[i] represents a local variable whose index is greater than the maximum number of local variables for the method.

    The 0th entry instack represents the verification type of the bottom of the operand stack, and subsequent entries instack represent the verification types of stack entries closer to the top of the operand stack. We refer to the bottom of the operand stack as stack entry 0, and to subsequent entries of the operand stack as stack entry 1, 2, etc. Ifstack[M] represents stack entryN, then:

    • stack[M+1] represents stack entryN+1 ifstack[M] is one ofTop_variable_info,Integer_variable_info,Float_variable_info,Null_variable_info,UninitializedThis_variable_info,Object_variable_info, orUninitialized_variable_info; and

    • stack[M+1] represents stack entryN+2 ifstack[M] is eitherLong_variable_info orDouble_variable_info.

    It is an error if, for any indexi,stack[i] represents a stack entry whose index is greater than the maximum operand stack size for the method.

4.7.5. TheExceptions Attribute

TheExceptions attribute is a variable-length attribute in theattributes table of amethod_info structure (§4.6). TheExceptions attribute indicates which checked exceptions a method may throw.

There may be at most oneExceptions attribute in theattributes table of amethod_info structure.

TheExceptions attribute has the following format:

Exceptions_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 number_of_exceptions;    u2 exception_index_table[number_of_exceptions];}

The items of theExceptions_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be theCONSTANT_Utf8_info structure (§4.4.7) representing the string "Exceptions".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

number_of_exceptions

The value of thenumber_of_exceptions item indicates the number of entries in theexception_index_table.

exception_index_table[]

Each value in theexception_index_table array must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure (§4.4.1) representing a class type that this method is declared to throw.

A method should throw an exception only if at least one of the following three criteria is met:

  • The exception is an instance ofRuntimeException or one of its subclasses.

  • The exception is an instance ofError or one of its subclasses.

  • The exception is an instance of one of the exception classes specified in theexception_index_table just described, or one of their subclasses.

These requirements are not enforced in the Java Virtual Machine; they are enforced only at compile time.

4.7.6. TheInnerClasses Attribute

TheInnerClasses attribute is a variable-length attribute in theattributes table of aClassFile structure (§4.1).

If the constant pool of a class or interfaceC contains at least oneCONSTANT_Class_info entry (§4.4.1) which represents a class or interface that is not a member of a package, then there must be exactly oneInnerClasses attribute in theattributes table of theClassFile structure forC.

TheInnerClasses attribute has the following format:

InnerClasses_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 number_of_classes;    {   u2 inner_class_info_index;        u2 outer_class_info_index;        u2 inner_name_index;        u2 inner_class_access_flags;    } classes[number_of_classes];}

The items of theInnerClasses_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "InnerClasses".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

number_of_classes

The value of thenumber_of_classes item indicates the number of entries in theclasses array.

classes[]

EveryCONSTANT_Class_info entry in theconstant_pool table which represents a class or interfaceC that is not a package member must have exactly one corresponding entry in theclasses array.

If a class or interface has members that are classes or interfaces, itsconstant_pool table (and hence itsInnerClasses attribute) must refer to each such member (JLS §13.1), even if that member is not otherwise mentioned by the class.

In addition, theconstant_pool table of every nested class and nested interface must refer to its enclosing class, so altogether, every nested class and nested interface will haveInnerClasses information for each enclosing class and for each of its own nested classes and interfaces.

Each entry in theclasses array contains the following four items:

inner_class_info_index

The value of theinner_class_info_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure representingC.

outer_class_info_index

IfC is not a member of a class or an interface - that is, ifC is a top-level class or interface (JLS §7.6) or a local class (JLS §14.3) or an anonymous class (JLS §15.9.5) - then the value of theouter_class_info_index item must be zero.

Otherwise, the value of theouter_class_info_index item must be a valid index into theconstant_pool table, and the entry at that index must be aCONSTANT_Class_info structure representing the class or interface of whichC is a member. The value of theouter_class_info_index item must not equal the the value of theinner_class_info_index item.

inner_name_index

IfC is anonymous (JLS §15.9.5), the value of theinner_name_index item must be zero.

Otherwise, the value of theinner_name_index item must be a valid index into theconstant_pool table, and the entry at that index must be aCONSTANT_Utf8_info structure that represents the original simple name ofC, as given in the source code from which thisclass file was compiled.

inner_class_access_flags

The value of theinner_class_access_flags item is a mask of flags used to denote access permissions to and properties of class or interfaceC as declared in the source code from which thisclass file was compiled. It is used by a compiler to recover the original information when source code is not available. The flags are specified inTable 4.7.6-A.

Table 4.7.6-A. Nested class access and property flags

Flag NameValueInterpretation
ACC_PUBLIC0x0001Marked or implicitlypublic in source.
ACC_PRIVATE0x0002Markedprivate in source.
ACC_PROTECTED0x0004Markedprotected in source.
ACC_STATIC0x0008Marked or implicitlystatic in source.
ACC_FINAL0x0010Marked or implicitlyfinal in source.
ACC_INTERFACE0x0200Was aninterface in source.
ACC_ABSTRACT0x0400Marked or implicitlyabstract in source.
ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
ACC_ANNOTATION0x2000Declared as an annotation interface.
ACC_ENUM0x4000Declared as anenum class.

All bits of theinner_class_access_flags item not assigned inTable 4.7.6-A are reserved for future use. They should be set to zero in generatedclass files and should be ignored by Java Virtual Machine implementations.

If aclass file has a version number that is 51.0 or above, and has anInnerClasses attribute in itsattributes table, then for all entries in theclasses array of theInnerClasses attribute, the value of theouter_class_info_index item must be zero if the value of theinner_name_index item is zero.

Oracle's Java Virtual Machine implementation does not check the consistency of anInnerClasses attribute against aclass file representing a class or interface referenced by the attribute.

4.7.7. TheEnclosingMethod Attribute

TheEnclosingMethod attribute is a fixed-length attribute in theattributes table of aClassFile structure (§4.1). A class must have anEnclosingMethod attribute if and only if it represents a local class or an anonymous class (JLS §14.3, JLS §15.9.5).

There may be at most oneEnclosingMethod attribute in theattributes table of aClassFile structure.

TheEnclosingMethod attribute has the following format:

EnclosingMethod_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 class_index;    u2 method_index;}

The items of theEnclosingMethod_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "EnclosingMethod".

attribute_length

The value of theattribute_length item must be four.

class_index

The value of theclass_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure (§4.4.1) representing the innermost class that encloses the declaration of the current class.

method_index

If the current class is not immediately enclosed by a method or constructor, then the value of themethod_index item must be zero.

In particular,method_index must be zero if the current class was immediately enclosed in source code by an instance initializer, static initializer, instance variable initializer, or class variable initializer. (The first two concern both local classes and anonymous classes, while the last two concern anonymous classes declared on the right hand side of a field assignment.)

Otherwise, the value of themethod_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_NameAndType_info structure (§4.4.6) representing the name and type of a method in the class referenced by theclass_index attribute above.

It is the responsibility of a Java compiler to ensure that the method identified via themethod_index is indeed the closest lexically enclosing method of the class that contains thisEnclosingMethod attribute.

4.7.8. TheSynthetic Attribute

TheSynthetic attribute is a fixed-length attribute in theattributes table of aClassFile,field_info, ormethod_info structure (§4.1,§4.5,§4.6). A class member that does not appear in the source code must be marked using aSynthetic attribute, or else it must have itsACC_SYNTHETIC flag set. The only exceptions to this requirement are compiler-generated members which are not considered implementation artifacts, namely:

  • an instance initialization method representing a default constructor of the Java programming language (§2.9.1)

  • a class or interface initialization method (§2.9.2)

  • the implicitly declared members of enum and record classes (JLS §8.9.3, JLS §8.10.3)

TheSynthetic attribute was introduced in JDK 1.1 to support nested classes and interfaces.

It is a limitation of theclass file format that only formal parameters and modules can be flagged asACC_MANDATED (§4.7.24,§4.7.25) to indicate that, despite being compiler-generated, they are not considered implementation artifacts. There is no way to flag other compiler-generated constructs so that they too are not considered implementation artifacts (JLS §13.1). This limitation means that reflective APIs of the Java SE Platform may not accurately indicate the "mandated" status of such constructs.

TheSynthetic attribute has the following format:

Synthetic_attribute {    u2 attribute_name_index;    u4 attribute_length;}

The items of theSynthetic_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "Synthetic".

attribute_length

The value of theattribute_length item must be zero.

4.7.9. TheSignature Attribute

TheSignature attribute is a fixed-length attribute in theattributes table of aClassFile,field_info,method_info, orrecord_component_info structure (§4.1,§4.5,§4.6,§4.7.30). ASignature attribute stores a signature (§4.7.9.1) for a class, interface, constructor, method, field, or record component whose declaration in the Java programming language uses type variables or parameterized types. SeeThe Java Language Specification, Java SE 24 Edition for details about these constructs.

There may be at most oneSignature attribute in theattributes table of aClassFile,field_info,method_info, orrecord_component_info structure.

TheSignature attribute has the following format:

Signature_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 signature_index;}

The items of theSignature_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "Signature".

attribute_length

The value of theattribute_length item must be two.

signature_index

The value of thesignature_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing a class signature if thisSignature attribute is an attribute of aClassFile structure; a method signature if thisSignature attribute is an attribute of amethod_info structure; or a field signature otherwise.

Oracle's Java Virtual Machine implementation does not check the well-formedness ofSignature attributes during class loading or linking. Instead,Signature attributes are checked by methods of the Java SE Platform class libraries which expose generic signatures of classes, interfaces, constructors, methods, and fields. Examples includegetGenericSuperclass inClass andtoGenericString injava.lang.reflect.Executable.

4.7.9.1. Signatures

Signatures encode declarations written in the Java programming language that use types outside the type system of the Java Virtual Machine. They support reflection and debugging, as well as compilation when onlyclass files are available.

A Java compiler must emit a signature for any class, interface, constructor, method, field, or record component whose declaration uses type variables or parameterized types. Specifically, a Java compiler must emit:

  • A class signature for any class or interface declaration which is either generic, or has a parameterized type as a superclass or superinterface, or both.

  • A method signature for any method or constructor declaration which is either generic, or has a type variable or parameterized type as the return type or a formal parameter type, or has a type variable in athrows clause, or any combination thereof.

    If thethrows clause of a method or constructor declaration does not involve type variables, then a compiler may treat the declaration as having nothrows clause for the purpose of emitting a method signature.

  • A field signature for any field, formal parameter, local variable, or record component declaration whose type uses a type variable or a parameterized type.

Signatures are specified using a grammar which follows the notation of§4.3.1. In addition to that notation:

  • The syntax[x] on the right-hand side of a production denotes zero or one occurrences ofx. That is,x is anoptional symbol. The alternative which contains the optional symbol actually defines two alternatives: one that omits the optional symbol and one that includes it.

  • A very long right-hand side may be continued on a second line by clearly indenting the second line.

The grammar includes the terminal symbolIdentifier to denote the name of a type, field, method, formal parameter, local variable, or type variable, as generated by a Java compiler. Such a name must not contain any of the ASCII characters.;[/<>: (that is, the characters forbidden in method names (§4.2.2) and also colon) but may contain characters that must not appear in an identifier in the Java programming language (JLS §3.8).

Signatures rely on a hierarchy of nonterminals known astype signatures:

Aclass signature encodes type information about a (possibly generic) class or interface declaration. It describes any type parameters of the class or interface, and lists its (possibly parameterized) direct superclass and direct superinterfaces, if any. A type parameter is described by its name, followed by any class bound and interface bounds.

TypeParameters:
TypeParameter:
ClassBound:
InterfaceBound:
SuperclassSignature:
SuperinterfaceSignature:

Amethod signature encodes type information about a (possibly generic) method declaration. It describes any type parameters of the method; the (possibly parameterized) types of any formal parameters; the (possibly parameterized) return type, if any; and the types of any exceptions declared in the method'sthrows clause.

The following production from§4.3.3 is repeated here for convenience:

VoidDescriptor:
V

A method signature encoded by theSignature attribute may not correspond exactly to the method descriptor in themethod_info structure (§4.3.3). In particular, there is no assurance that the number of formal parameter types in the method signature is the same as the number of parameter descriptors in the method descriptor. The numbers are the same for most methods, but certain constructors in the Java programming language have an implicitly declared parameter which a compiler represents with a parameter descriptor but may omit from the method signature. See the note in§4.7.18 for a similar situation involving parameter annotations.

Afield signature encodes the (possibly parameterized) type of a field, formal parameter, local variable, or record component declaration.

FieldSignature:

4.7.10. TheSourceFile Attribute

TheSourceFile attribute is an optional fixed-length attribute in theattributes table of aClassFile structure (§4.1).

There may be at most oneSourceFile attribute in theattributes table of aClassFile structure.

TheSourceFile attribute has the following format:

SourceFile_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 sourcefile_index;}

The items of theSourceFile_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "SourceFile".

attribute_length

The value of theattribute_length item must be two.

sourcefile_index

The value of thesourcefile_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure representing a string.

The string referenced by thesourcefile_index item will be interpreted as indicating the name of the source file from which thisclass file was compiled. It will not be interpreted as indicating the name of a directory containing the file or an absolute path name for the file; such platform-specific additional information must be supplied by the run-time interpreter or development tool at the time the file name is actually used.

4.7.11. TheSourceDebugExtension Attribute

TheSourceDebugExtension attribute is an optional attribute in theattributes table of aClassFile structure (§4.1).

There may be at most oneSourceDebugExtension attribute in theattributes table of aClassFile structure.

TheSourceDebugExtension attribute has the following format:

SourceDebugExtension_attribute {    u2 attribute_name_index;    u4 attribute_length;    u1 debug_extension[attribute_length];}

The items of theSourceDebugExtension_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "SourceDebugExtension".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

debug_extension[]

Thedebug_extension array holds extended debugging information which has no semantic effect on the Java Virtual Machine. The information is represented using a modified UTF-8 string (§4.4.7) with no terminating zero byte.

Note that thedebug_extension array may denote a string longer than that which can be represented with an instance of classString.

4.7.12. TheLineNumberTable Attribute

TheLineNumberTable attribute is an optional variable-length attribute in theattributes table of aCode attribute (§4.7.3). It may be used by debuggers to determine which part of thecode array corresponds to a given line number in the original source file.

If multipleLineNumberTable attributes are present in theattributes table of aCode attribute, then they may appear in any order.

There may be more than oneLineNumberTable attributeper line of a source file in theattributes table of aCode attribute. That is,LineNumberTable attributes may together represent a given line of a source file, and need not be one-to-one with source lines.

TheLineNumberTable attribute has the following format:

LineNumberTable_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 line_number_table_length;    {   u2 start_pc;        u2 line_number;    } line_number_table[line_number_table_length];}

The items of theLineNumberTable_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "LineNumberTable".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

line_number_table_length

The value of theline_number_table_length item indicates the number of entries in theline_number_table array.

line_number_table[]

Each entry in theline_number_table array indicates that the line number in the original source file changes at a given point in thecode array. Eachline_number_table entry must contain the following two items:

start_pc

The value of thestart_pc item must be a valid index into thecode array of thisCode attribute. The item indicates the index into thecode array at which the code for a new line in the original source file begins.

line_number

The value of theline_number item gives the corresponding line number in the original source file.

4.7.13. TheLocalVariableTable Attribute

TheLocalVariableTable attribute is an optional variable-length attribute in theattributes table of aCode attribute (§4.7.3). It may be used by debuggers to determine the value of a given local variable during the execution of a method.

If multipleLocalVariableTable attributes are present in theattributes table of aCode attribute, then they may appear in any order.

There may be no more than oneLocalVariableTable attributeper local variable in theattributes table of aCode attribute.

TheLocalVariableTable attribute has the following format:

LocalVariableTable_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 local_variable_table_length;    {   u2 start_pc;        u2 length;        u2 name_index;        u2 descriptor_index;        u2 index;    } local_variable_table[local_variable_table_length];}

The items of theLocalVariableTable_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "LocalVariableTable".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

local_variable_table_length

The value of thelocal_variable_table_length item indicates the number of entries in thelocal_variable_table array.

local_variable_table[]

Each entry in thelocal_variable_table array indicates a range ofcode array offsets within which a local variable has a value, and indicates the index into the local variable array of the current frame at which that local variable can be found. Each entry must contain the following five items:

start_pc, length

The value of thestart_pc item must be a valid index into thecode array of thisCode attribute and must be the index of the opcode of an instruction.

The value ofstart_pc + length must either be a valid index into thecode array of thisCode attribute and be the index of the opcode of an instruction, or it must be the first index beyond the end of thatcode array.

Thestart_pc andlength items indicate that the given local variable has a value at indices into thecode array in the interval [start_pc,start_pc + length), that is, betweenstart_pc inclusive andstart_pc + length exclusive.

name_index

The value of thename_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must contain aCONSTANT_Utf8_info structure representing a valid unqualified name denoting a local variable (§4.2.2).

descriptor_index

The value of thedescriptor_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must contain aCONSTANT_Utf8_info structure representing a field descriptor which encodes the type of a local variable in the source program (§4.3.2).

index

The value of theindex item must be a valid index into the local variable array of the current frame. The given local variable is atindex in the local variable array of the current frame.

If the given local variable is of typedouble orlong, it occupies bothindex andindex + 1.

4.7.14. TheLocalVariableTypeTable Attribute

TheLocalVariableTypeTable attribute is an optional variable-length attribute in theattributes table of aCode attribute (§4.7.3). It may be used by debuggers to determine the value of a given local variable during the execution of a method.

If multipleLocalVariableTypeTable attributes are present in theattributes table of a givenCode attribute, then they may appear in any order.

There may be no more than oneLocalVariableTypeTable attributeper local variable in theattributes table of aCode attribute.

TheLocalVariableTypeTable attribute differs from theLocalVariableTable attribute (§4.7.13) in that it provides signature information rather than descriptor information. This difference is only significant for variables whose type uses a type variable or parameterized type. Such variables will appear in both tables, while variables of other types will appear only inLocalVariableTable.

TheLocalVariableTypeTable attribute has the following format:

LocalVariableTypeTable_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 local_variable_type_table_length;    {   u2 start_pc;        u2 length;        u2 name_index;        u2 signature_index;        u2 index;    } local_variable_type_table[local_variable_type_table_length];}

The items of theLocalVariableTypeTable_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "LocalVariableTypeTable".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

local_variable_type_table_length

The value of thelocal_variable_type_table_length item indicates the number of entries in thelocal_variable_type_table array.

local_variable_type_table[]

Each entry in thelocal_variable_type_table array indicates a range ofcode array offsets within which a local variable has a value, and indicates the index into the local variable array of the current frame at which that local variable can be found. Each entry must contain the following five items:

start_pc, length

The value of thestart_pc item must be a valid index into thecode array of thisCode attribute and must be the index of the opcode of an instruction.

The value ofstart_pc + length must either be a valid index into thecode array of thisCode attribute and be the index of the opcode of an instruction, or it must be the first index beyond the end of thatcode array.

Thestart_pc andlength items indicate that the given local variable has a value at indices into thecode array in the interval [start_pc,start_pc + length), that is, betweenstart_pc inclusive andstart_pc + length exclusive.

name_index

The value of thename_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must contain aCONSTANT_Utf8_info structure representing a valid unqualified name denoting a local variable (§4.2.2).

signature_index

The value of thesignature_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must contain aCONSTANT_Utf8_info structure representing a field signature which encodes the type of a local variable in the source program (§4.7.9.1).

index

The value of theindex item must be a valid index into the local variable array of the current frame. The given local variable is atindex in the local variable array of the current frame.

If the given local variable is of typedouble orlong, it occupies bothindex andindex + 1.

4.7.15. TheDeprecated Attribute

TheDeprecated attribute is an optional fixed-length attribute in theattributes table of aClassFile,field_info, ormethod_info structure (§4.1,§4.5,§4.6). A class, interface, method, or field may be marked using aDeprecated attribute to indicate that the class, interface, method, or field has been superseded.

A run-time interpreter or tool that reads theclass file format, such as a compiler, can use this marking to advise the user that a superseded class, interface, method, or field is being referred to. The presence of aDeprecated attribute does not alter the semantics of a class or interface.

TheDeprecated attribute has the following format:

Deprecated_attribute {    u2 attribute_name_index;    u4 attribute_length;}

The items of theDeprecated_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "Deprecated".

attribute_length

The value of theattribute_length item must be zero.

4.7.16. TheRuntimeVisibleAnnotations Attribute

TheRuntimeVisibleAnnotations attribute is a variable-length attribute in theattributes table of aClassFile,field_info,method_info, orrecord_component_info structure (§4.1,§4.5,§4.6,§4.7.30). TheRuntimeVisibleAnnotations attribute stores run-time visible annotations on the declaration of the corresponding class, field, method, or record component.

There may be at most oneRuntimeVisibleAnnotations attribute in theattributes table of aClassFile,field_info,method_info, orrecord_component_info structure.

TheRuntimeVisibleAnnotations attribute has the following format:

RuntimeVisibleAnnotations_attribute {    u2         attribute_name_index;    u4         attribute_length;    u2         num_annotations;    annotation annotations[num_annotations];}

The items of theRuntimeVisibleAnnotations_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "RuntimeVisibleAnnotations".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

num_annotations

The value of thenum_annotations item gives the number of run-time visible annotations represented by the structure.

annotations[]

Each entry in theannotations table represents a single run-time visible annotation on a declaration. Theannotation structure has the following format:

annotation {    u2 type_index;    u2 num_element_value_pairs;    {   u2            element_name_index;        element_value value;    } element_value_pairs[num_element_value_pairs];}

The items of theannotation structure are as follows:

type_index

The value of thetype_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing a field descriptor (§4.3.2). The field descriptor denotes the type of the annotation represented by thisannotation structure.

num_element_value_pairs

The value of thenum_element_value_pairs item gives the number of element-value pairs of the annotation represented by thisannotation structure.

element_value_pairs[]

Each value of theelement_value_pairs table represents a single element-value pair in the annotation represented by thisannotation structure. Eachelement_value_pairs entry contains the following two items:

element_name_index

The value of theelement_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7). Theconstant_pool entry denotes the name of the element of the element-value pair represented by thiselement_value_pairs entry.

In other words, the entry denotes an element of the annotation interface specified bytype_index.

value

The value of thevalue item represents the value of the element-value pair represented by thiselement_value_pairs entry.

4.7.16.1. Theelement_value structure

Theelement_value structure is a discriminated union representing the value of an element-value pair. It has the following format:

element_value {    u1 tag;    union {        u2 const_value_index;        {   u2 type_name_index;            u2 const_name_index;        } enum_const_value;        u2 class_info_index;        annotation annotation_value;        {   u2            num_values;            element_value values[num_values];        } array_value;    } value;}

Thetag item uses a single ASCII character to indicate the type of the value of the element-value pair. This determines which item of thevalue union is in use.Table 4.7.16.1-A shows the valid characters for thetag item, the type indicated by each character, and the item used in thevalue union for each character. The table's fourth column is used in the description below of one item of thevalue union.

Table 4.7.16.1-A. Interpretation oftag values as types

tag ItemTypevalue ItemConstant Type
Bbyteconst_value_indexCONSTANT_Integer
Ccharconst_value_indexCONSTANT_Integer
Ddoubleconst_value_indexCONSTANT_Double
Ffloatconst_value_indexCONSTANT_Float
Iintconst_value_indexCONSTANT_Integer
Jlongconst_value_indexCONSTANT_Long
Sshortconst_value_indexCONSTANT_Integer
Zbooleanconst_value_indexCONSTANT_Integer
sStringconst_value_indexCONSTANT_Utf8
eEnum classenum_const_valueNot applicable
cClassclass_info_indexNot applicable
@Annotation interfaceannotation_valueNot applicable
[Array typearray_valueNot applicable

Thevalue item represents the value of an element-value pair. The item is a union, whose own items are as follows:

const_value_index

Theconst_value_index item denotes a constant of either a primitive type or the typeString as the value of this element-value pair.

The value of theconst_value_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be of a type appropriate to thetag item, as specified in the fourth column ofTable 4.7.16.1-A.

enum_const_value

Theenum_const_value item denotes an enum constant as the value of this element-value pair.

Theenum_const_value item consists of the following two items:

type_name_index

The value of thetype_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing a field descriptor (§4.3.2). Theconstant_pool entry gives the internal form of the binary name of the type of the enum constant represented by thiselement_value structure (§4.2.1).

const_name_index

The value of theconst_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7). Theconstant_pool entry gives the simple name of the enum constant represented by thiselement_value structure.

class_info_index

Theclass_info_index item denotes a class literal as the value of this element-value pair.

Theclass_info_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing a return descriptor (§4.3.3). The return descriptor gives the type corresponding to the class literal represented by thiselement_value structure. Types correspond to class literals as follows:

  • For a class literalC.class, whereC is the name of a class, interface, or array type, the corresponding type isC. The return descriptor in theconstant_pool will be aClassType or anArrayType.

  • For a class literalp.class, wherep is the name of a primitive type, the corresponding type isp. The return descriptor in theconstant_pool will be aBaseType character.

  • For a class literalvoid.class, the corresponding type isvoid. The return descriptor in theconstant_pool will beV.

For example, the class literalObject.class corresponds to the typeObject, so theconstant_pool entry isLjava/lang/Object;, whereas the class literalint.class corresponds to the typeint, so theconstant_pool entry isI.

The class literalvoid.class corresponds tovoid, so theconstant_pool entry isV, whereas the class literalVoid.class corresponds to the typeVoid, so theconstant_pool entry isLjava/lang/Void;.

annotation_value

Theannotation_value item denotes a "nested" annotation as the value of this element-value pair.

The value of theannotation_value item is anannotation structure (§4.7.16) that gives the annotation represented by thiselement_value structure.

array_value

Thearray_value item denotes an array as the value of this element-value pair.

Thearray_value item consists of the following two items:

num_values

The value of thenum_values item gives the number of elements in the array represented by thiselement_value structure.

values[]

Each value in thevalues table gives the corresponding element of the array represented by thiselement_value structure.

4.7.17. TheRuntimeInvisibleAnnotations Attribute

TheRuntimeInvisibleAnnotations attribute is a variable-length attribute in theattributes table of aClassFile,field_info,method_info, orrecord_component_info structure (§4.1,§4.5,§4.6,§4.7.30). TheRuntimeInvisibleAnnotations attribute stores run-time invisible annotations on the declaration of the corresponding class, method, field, or record component.

There may be at most oneRuntimeInvisibleAnnotations attribute in theattributes table of aClassFile,field_info,method_info, orrecord_component_info structure.

TheRuntimeInvisibleAnnotations attribute is similar to theRuntimeVisibleAnnotations attribute (§4.7.16), except that the annotations represented by aRuntimeInvisibleAnnotations attribute must not be made available for return by reflective APIs, unless the Java Virtual Machine has been instructed to retain these annotations via some implementation-specific mechanism such as a command line flag. In the absence of such instructions, the Java Virtual Machine ignores this attribute.

TheRuntimeInvisibleAnnotations attribute has the following format:

RuntimeInvisibleAnnotations_attribute {    u2         attribute_name_index;    u4         attribute_length;    u2         num_annotations;    annotation annotations[num_annotations];}

The items of theRuntimeInvisibleAnnotations_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "RuntimeInvisibleAnnotations".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

num_annotations

The value of thenum_annotations item gives the number of run-time invisible annotations represented by the structure.

annotations[]

Each entry in theannotations table represents a single run-time invisible annotation on a declaration. Theannotation structure is specified in§4.7.16.

4.7.18. TheRuntimeVisibleParameterAnnotations Attribute

TheRuntimeVisibleParameterAnnotations attribute is a variable-length attribute in theattributes table of themethod_info structure (§4.6). TheRuntimeVisibleParameterAnnotations attribute stores run-time visible annotations on the declarations of formal parameters of the corresponding method.

There may be at most oneRuntimeVisibleParameterAnnotations attribute in theattributes table of amethod_info structure.

TheRuntimeVisibleParameterAnnotations attribute has the following format:

RuntimeVisibleParameterAnnotations_attribute {    u2 attribute_name_index;    u4 attribute_length;    u1 num_parameters;    {   u2         num_annotations;        annotation annotations[num_annotations];    } parameter_annotations[num_parameters];}

The items of theRuntimeVisibleParameterAnnotations_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "RuntimeVisibleParameterAnnotations".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

num_parameters

The value of thenum_parameters item gives the number of run-time visible parameter annotations represented by this structure.

There is no assurance that this number is the same as the number of parameter descriptors in the method descriptor.

parameter_annotations[]

Each entry in theparameter_annotations table represents all of the run-time visible annotations on the declaration of a single formal parameter. Eachparameter_annotations entry contains the following two items:

num_annotations

The value of thenum_annotations item indicates the number of run-time visible annotations on the declaration of the formal parameter corresponding to theparameter_annotations entry.

annotations[]

Each entry in theannotations table represents a single run-time visible annotation on the declaration of the formal parameter corresponding to theparameter_annotations entry. Theannotation structure is specified in§4.7.16.

Thei'th entry in theparameter_annotations table may, but is not required to, correspond to thei'th parameter descriptor in the method descriptor (§4.3.3).

For example, a compiler may choose to create entries in the table corresponding only to those parameter descriptors which represent explicitly declared parameters in source code. In the Java programming language, a constructor of an inner class is specified to have an implicitly declared parameter before its explicitly declared parameters (JLS §8.8.1), so the corresponding<init> method in aclass file has a parameter descriptor representing the implicitly declared parameter before any parameter descriptors representing explicitly declared parameters. If the first explicitly declared parameter is annotated in source code, then a compiler may createparameter_annotations[0] to store annotations corresponding to thesecond parameter descriptor.

4.7.19. TheRuntimeInvisibleParameterAnnotations Attribute

TheRuntimeInvisibleParameterAnnotations attribute is a variable-length attribute in theattributes table of amethod_info structure (§4.6). TheRuntimeInvisibleParameterAnnotations attribute stores run-time invisible annotations on the declarations of formal parameters of the corresponding method.

There may be at most oneRuntimeInvisibleParameterAnnotations attribute in theattributes table of amethod_info structure.

TheRuntimeInvisibleParameterAnnotations attribute is similar to theRuntimeVisibleParameterAnnotations attribute (§4.7.18), except that the annotations represented by aRuntimeInvisibleParameterAnnotations attribute must not be made available for return by reflective APIs, unless the Java Virtual Machine has specifically been instructed to retain these annotations via some implementation-specific mechanism such as a command line flag. In the absence of such instructions, the Java Virtual Machine ignores this attribute.

TheRuntimeInvisibleParameterAnnotations attribute has the following format:

RuntimeInvisibleParameterAnnotations_attribute {    u2 attribute_name_index;    u4 attribute_length;    u1 num_parameters;    {   u2         num_annotations;        annotation annotations[num_annotations];    } parameter_annotations[num_parameters];}

The items of theRuntimeInvisibleParameterAnnotations_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "RuntimeInvisibleParameterAnnotations".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

num_parameters

The value of thenum_parameters item gives the number of run-time invisible parameter annotations represented by this structure.

There is no assurance that this number is the same as the number of parameter descriptors in the method descriptor.

parameter_annotations[]

Each entry in theparameter_annotations table represents all of the run-time invisible annotations on the declaration of a single formal parameter. Eachparameter_annotations entry contains the following two items:

num_annotations

The value of thenum_annotations item indicates the number of run-time invisible annotations on the declaration of the formal parameter corresponding to theparameter_annotations entry.

annotations[]

Each entry in theannotations table represents a single run-time invisible annotation on the declaration of the formal parameter corresponding to theparameter_annotations entry. Theannotation structure is specified in§4.7.16.

Thei'th entry in theparameter_annotations table may, but is not required to, correspond to thei'th parameter descriptor in the method descriptor (§4.3.3).

See the note in§4.7.18 for an example of whenparameter_annotations[0] does not correspond to the first parameter descriptor in the method descriptor.

4.7.20. TheRuntimeVisibleTypeAnnotations Attribute

TheRuntimeVisibleTypeAnnotations attribute is an variable-length attribute in theattributes table of aClassFile,field_info,method_info, orrecord_component_info structure, orCode attribute (§4.1,§4.5,§4.6,§4.7.30,§4.7.3). TheRuntimeVisibleTypeAnnotations attribute stores run-time visible annotations on types used in the declaration of the corresponding class, field, method, or record component, or in an expression in the corresponding method body. TheRuntimeVisibleTypeAnnotations attribute also stores run-time visible annotations on type parameter declarations of generic classes, interfaces, methods, and constructors.

There may be at most oneRuntimeVisibleTypeAnnotations attribute in theattributes table of aClassFile,field_info,method_info, orrecord_component_info structure, orCode attribute.

Anattributes table contains aRuntimeVisibleTypeAnnotations attribute only if types are annotated in kinds of declaration or expression that correspond to the parent structure or attribute of theattributes table.

For example, all annotations on types in theimplements clause of a class declaration are recorded in theRuntimeVisibleTypeAnnotations attribute of the class'sClassFile structure. Meanwhile, all annotations on the type in a field declaration are recorded in theRuntimeVisibleTypeAnnotations attribute of the field'sfield_info structure.

TheRuntimeVisibleTypeAnnotations attribute has the following format:

RuntimeVisibleTypeAnnotations_attribute {    u2              attribute_name_index;    u4              attribute_length;    u2              num_annotations;    type_annotation annotations[num_annotations];}

The items of theRuntimeVisibleTypeAnnotations_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure representing the string "RuntimeVisibleTypeAnnotations".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

num_annotations

The value of thenum_annotations item gives the number of run-time visible type annotations represented by the structure.

annotations[]

Each entry in theannotations table represents a single run-time visible annotation on a type used in a declaration or expression. Thetype_annotation structure has the following format:

type_annotation {    u1 target_type;    union {        type_parameter_target;        supertype_target;        type_parameter_bound_target;        empty_target;        formal_parameter_target;        throws_target;        localvar_target;        catch_target;        offset_target;        type_argument_target;    } target_info;    type_path target_path;    u2        type_index;    u2        num_element_value_pairs;    {   u2            element_name_index;        element_value value;    } element_value_pairs[num_element_value_pairs];}

The first three items -target_type,target_info, andtarget_path - specify the precise location of the annotated type. The last three items -type_index,num_element_value_pairs, andelement_value_pairs[] - specify the annotation's own type and element-value pairs.

The items of thetype_annotation structure are as follows:

target_type

The value of thetarget_type item denotes the kind of target on which the annotation appears. The various kinds of target correspond to thetype contexts of the Java programming language where types are used in declarations and expressions (JLS §4.11).

The legal values oftarget_type are specified inTable 4.7.20-A andTable 4.7.20-B. Each value is a one-byte tag indicating which item of thetarget_info union follows thetarget_type item to give more information about the target.

The kinds of target inTable 4.7.20-A andTable 4.7.20-B correspond to the type contexts in JLS §4.11. Namely,target_type values 0x10-0x17 and 0x40-0x42 correspond to type contexts 1-11, whiletarget_type values 0x43-0x4B correspond to type contexts 12-17.

The value of thetarget_type item determines whether thetype_annotation structure appears in aRuntimeVisibleTypeAnnotations attribute in aClassFile structure, afield_info structure, amethod_info structure, or aCode attribute.Table 4.7.20-C gives the location of theRuntimeVisibleTypeAnnotations attribute for atype_annotation structure with each legaltarget_type value.

target_info

The value of thetarget_info item denotes precisely which type in a declaration or expression is annotated.

The items of thetarget_info union are specified in§4.7.20.1.

target_path

The value of thetarget_path item denotes precisely which part of the type indicated bytarget_info is annotated.

The format of thetype_path structure is specified in§4.7.20.2.

type_index, num_element_value_pairs, element_value_pairs[]

The meaning of these items in thetype_annotation structure is the same as their meaning in theannotation structure (§4.7.16).

Table 4.7.20-A. Interpretation oftarget_type values (Part 1)

ValueKind of targettarget_info item
0x00type parameter declaration of generic class or interfacetype_parameter_target
0x01type parameter declaration of generic method or constructortype_parameter_target
0x10type inextends orimplements clause of class declaration (including the direct superclass or direct superinterface of an anonymous class declaration), or inextends clause of interface declarationsupertype_target
0x11type in bound of type parameter declaration of generic class or interfacetype_parameter_bound_target
0x12type in bound of type parameter declaration of generic method or constructortype_parameter_bound_target
0x13

type in field or record component declaration

empty_target
0x14return type of method, or type of newly constructed objectempty_target
0x15receiver type of method or constructorempty_target
0x16type in formal parameter declaration of method, constructor, or lambda expressionformal_parameter_target
0x17type inthrows clause of method or constructorthrows_target

Table 4.7.20-B. Interpretation oftarget_type values (Part 2)

ValueKind of targettarget_info item
0x40type in local variable declarationlocalvar_target
0x41type in resource variable declarationlocalvar_target
0x42type in exception parameter declarationcatch_target
0x43type ininstanceof expressionoffset_target
0x44type innew expressionoffset_target
0x45type in method reference expression using::newoffset_target
0x46type in method reference expression using::Identifieroffset_target
0x47type in cast expressiontype_argument_target
0x48type argument for generic constructor innew expression or explicit constructor invocation statementtype_argument_target
0x49type argument for generic method in method invocation expressiontype_argument_target
0x4Atype argument for generic constructor in method reference expression using::newtype_argument_target
0x4Btype argument for generic method in method reference expression using::Identifiertype_argument_target

Table 4.7.20-C. Location of enclosing attribute fortarget_type values

ValueKind of targetLocation
0x00type parameter declaration of generic class or interfaceClassFile
0x01type parameter declaration of generic method or constructormethod_info
0x10type inextends clause of class or interface declaration, or inimplements clause of interface declarationClassFile
0x11type in bound of type parameter declaration of generic class or interfaceClassFile
0x12type in bound of type parameter declaration of generic method or constructormethod_info
0x13

type in field or record component declaration

field_info,record_component_info

0x14return type of method or constructormethod_info
0x15receiver type of method or constructormethod_info
0x16type in formal parameter declaration of method, constructor, or lambda expressionmethod_info
0x17type inthrows clause of method or constructormethod_info
0x40-0x4Btypes in local variable declarations, resource variable declarations, exception parameter declarations, expressionsCode

4.7.20.1. Thetarget_info union

The items of thetarget_info union (except for the first) specify precisely which type in a declaration or expression is annotated. The first item specifies not which type, but rather which declaration of a type parameter is annotated. The items are as follows:

  • Thetype_parameter_target item indicates that an annotation appears on the declaration of thei'th type parameter of a generic class, generic interface, generic method, or generic constructor.

    type_parameter_target {    u1 type_parameter_index;}

    The value of thetype_parameter_index item specifies which type parameter declaration is annotated. Atype_parameter_index value of0 specifies the first type parameter declaration.

  • Thesupertype_target item indicates that an annotation appears on a type in theextends orimplements clause of a class or interface declaration.

    supertype_target {    u2 supertype_index;}

    Asupertype_index value of 65535 specifies that the annotation appears on the superclass in anextends clause of a class declaration.

    Any othersupertype_index value is an index into theinterfaces array of the enclosingClassFile structure, and specifies that the annotation appears on that superinterface in either theimplements clause of a class declaration or theextends clause of an interface declaration.

  • Thetype_parameter_bound_target item indicates that an annotation appears on thei'th bound of thej'th type parameter declaration of a generic class, interface, method, or constructor.

    type_parameter_bound_target {    u1 type_parameter_index;    u1 bound_index;}

    The value of the oftype_parameter_index item specifies which type parameter declaration has an annotated bound. Atype_parameter_index value of0 specifies the first type parameter declaration.

    The value of thebound_index item specifies which bound of the type parameter declaration indicated bytype_parameter_index is annotated. Abound_index value of0 specifies the first bound of a type parameter declaration.

    Thetype_parameter_bound_target item records that a bound is annotated, but does not record the type which constitutes the bound. The type may be found by inspecting the class signature or method signature stored in the appropriateSignature attribute.

  • Theempty_target item indicates that an annotation appears on either the type in a field declaration, the type in a record component declaration, the return type of a method, the type of a newly constructed object, or the receiver type of a method or constructor.

    empty_target {}

    Only one type appears in each of these locations, so there is no per-type information to represent in thetarget_info union.

  • Theformal_parameter_target item indicates that an annotation appears on the type in a formal parameter declaration of a method, constructor, or lambda expression.

    formal_parameter_target {    u1 formal_parameter_index;}

    The value of theformal_parameter_index item specifies which formal parameter declaration has an annotated type. Aformal_parameter_index value ofi may, but is not required to, correspond to thei'th parameter descriptor in the method descriptor (§4.3.3).

    Theformal_parameter_target item records that a formal parameter's type is annotated, but does not record the type itself. The type may be found by inspecting the method descriptor, although aformal_parameter_index value of0 does not always indicate the first parameter descriptor in the method descriptor; see the note in§4.7.18 for a similar situation involving theparameter_annotations table.

  • Thethrows_target item indicates that an annotation appears on thei'th type in thethrows clause of a method or constructor declaration.

    throws_target {    u2 throws_type_index;}

    The value of thethrows_type_index item is an index into theexception_index_table array of theExceptions attribute of themethod_info structure enclosing theRuntimeVisibleTypeAnnotations attribute.

  • Thelocalvar_target item indicates that an annotation appears on the type in a local variable declaration, including a variable declared as a resource in atry-with-resources statement.

    localvar_target {    u2 table_length;    {   u2 start_pc;        u2 length;        u2 index;    } table[table_length];}

    The value of thetable_length item gives the number of entries in thetable array. Each entry indicates a range ofcode array offsets within which a local variable has a value. It also indicates the index into the local variable array of the current frame at which that local variable can be found. Each entry contains the following three items:

    start_pc, length

    The given local variable has a value at indices into thecode array in the interval [start_pc,start_pc + length), that is, betweenstart_pc inclusive andstart_pc + length exclusive.

    index

    The given local variable must be atindex in the local variable array of the current frame.

    If the local variable atindex is of typedouble orlong, it occupies bothindex andindex + 1.

    A table is needed to fully specify the local variable whose type is annotated, because a single local variable may be represented with different local variable indices over multiple live ranges. Thestart_pc,length, andindex items in each table entry specify the same information as aLocalVariableTable attribute.

    Thelocalvar_target item records that a local variable's type is annotated, but does not record the type itself. The type may be found by inspecting the appropriateLocalVariableTable attribute.

  • Thecatch_target item indicates that an annotation appears on thei'th type in an exception parameter declaration.

    catch_target {    u2 exception_table_index;}

    The value of theexception_table_index item is an index into theexception_table array of theCode attribute enclosing theRuntimeVisibleTypeAnnotations attribute.

    The possibility of more than one type in an exception parameter declaration arises from the multi-catch clause of thetry statement, where the type of the exception parameter is a union of types (JLS §14.20). A compiler usually creates oneexception_table entry for each type in the union, which allows thecatch_target item to distinguish them. This preserves the correspondence between a type and its annotations.

  • Theoffset_target item indicates that an annotation appears on either the type in aninstanceof expression or anew expression, or the type before the:: in a method reference expression.

    offset_target {    u2 offset;}

    The value of theoffset item specifies thecode array offset of either the bytecode instruction corresponding to theinstanceof expression, thenew bytecode instruction corresponding to thenew expression, or the bytecode instruction corresponding to the method reference expression.

  • Thetype_argument_target item indicates that an annotation appears either on thei'th type in a cast expression, or on thei'th type argument in the explicit type argument list for any of the following: anew expression, an explicit constructor invocation statement, a method invocation expression, or a method reference expression.

    type_argument_target {    u2 offset;    u1 type_argument_index;}

    The value of theoffset item specifies thecode array offset of either the bytecode instruction corresponding to the cast expression, thenew bytecode instruction corresponding to thenew expression, the bytecode instruction corresponding to the explicit constructor invocation statement, the bytecode instruction corresponding to the method invocation expression, or the bytecode instruction corresponding to the method reference expression.

    For a cast expression, the value of thetype_argument_index item specifies which type in the cast operator is annotated. Atype_argument_index value of0 specifies the first (or only) type in the cast operator.

    The possibility of more than one type in a cast expression arises from a cast to an intersection type.

    For an explicit type argument list, the value of thetype_argument_index item specifies which type argument is annotated. Atype_argument_index value of0 specifies the first type argument.

4.7.20.2. Thetype_path structure

Wherever a type is used in a declaration or expression, thetype_path structure identifies which part of the type is annotated. An annotation may appear on the type itself, but if the type is a reference type, then there are additional locations where an annotation may appear:

  • If an array typeT[] is used in a declaration or expression, then an annotation may appear on any component type of the array type, including the element type.

  • If a nested typeT1.T2 is used in a declaration or expression, then an annotation may appear on the name of the innermost member type and any enclosing type for which a type annotation is admissible (JLS §9.7.4).

  • If a parameterized typeT<A> orT<? extends A> orT<? super A> is used in a declaration or expression, then an annotation may appear on any type argument or on the bound of any wildcard type argument.

For example, consider the different parts ofString[][] that are annotated in:

@Foo String[][]   // Annotates the class type StringString @Foo [][]  // Annotates the array type String[][]String[] @Foo []  // Annotates the array type String[]

or the different parts of the nested typeOuter.Middle.Inner that are annotated in:

@Foo Outer.Middle.InnerOuter.@Foo Middle.InnerOuter.Middle.@Foo Inner

or the different parts of the parameterized typesMap<String,Object> andList<...> that are annotated in:

@Foo Map<String,Object>Map<@Foo String,Object>Map<String,@Foo Object>List<@Foo ? extends String>List<? extends @Foo String>

Thetype_path structure has the following format:

type_path {    u1 path_length;    {   u1 type_path_kind;        u1 type_argument_index;    } path[path_length];}

The value of thepath_length item gives the number of entries in thepath array:

  • If the value ofpath_length is0, and the type being annotated is a nested type, then the annotation applies to the outermost part of the type for which a type annotation is admissible.

  • If the value ofpath_length is0, and the type being annotated is not a nested type, then the annotation appears directly on the type itself.

  • If the value ofpath_length is non-zero, then each entry in thepath array represents an iterative, left-to-right step towards the precise location of the annotation in an array type, nested type, or parameterized type. (In an array type, the iteration visits the array type itself, then its component type, then the component type of that component type, and so on, until the element type is reached.) Each entry contains the following two items:

    type_path_kind

    The legal values for thetype_path_kind item are listed inTable 4.7.20.2-A.

    Table 4.7.20.2-A. Interpretation oftype_path_kind values

    ValueInterpretation
    0Annotation is deeper in an array type
    1Annotation is deeper in a nested type
    2Annotation is on the bound of a wildcard type argument of a parameterized type
    3Annotation is on a type argument of a parameterized type

    type_argument_index

    If the value of thetype_path_kind item is0,1, or2, then the value of thetype_argument_index item is0.

    If the value of thetype_path_kind item is3, then the value of thetype_argument_index item specifies which type argument of a parameterized type is annotated, where0 indicates the first type argument of a parameterized type.

Table 4.7.20.2-B. type_path structures for@A Map<@B ? extends @C String, @D List<@E Object>>

Annotationpath_lengthpath
@A0[]
@B1[{type_path_kind: 3; type_argument_index: 0}]
@C2[{type_path_kind: 3; type_argument_index: 0}, {type_path_kind: 2; type_argument_index: 0}]
@D1[{type_path_kind: 3; type_argument_index: 1}]
@E2[{type_path_kind: 3; type_argument_index: 1}, {type_path_kind: 3; type_argument_index: 0}]

Table 4.7.20.2-C. type_path structures for@I String @F [] @G [] @H []

Annotationpath_lengthpath
@F0[]
@G1[{type_path_kind: 0; type_argument_index: 0}]
@H2[{type_path_kind: 0; type_argument_index: 0}, {type_path_kind: 0; type_argument_index: 0}]
@I3[{type_path_kind: 0; type_argument_index: 0}, {type_path_kind: 0; type_argument_index: 0}, {type_path_kind: 0; type_argument_index: 0}]

Table 4.7.20.2-D. type_path structures for@A List<@B Comparable<@F Object @C [] @D [] @E []>>

Annotationpath_lengthpath
@A0[]
@B1[{type_path_kind: 3; type_argument_index: 0}]
@C2[{type_path_kind: 3; type_argument_index: 0}, {type_path_kind: 3; type_argument_index: 0}]
@D3[{type_path_kind: 3; type_argument_index: 0}, {type_path_kind: 3; type_argument_index: 0}, {type_path_kind: 0; type_argument_index: 0}]
@E4[{type_path_kind: 3; type_argument_index: 0}, {type_path_kind: 3; type_argument_index: 0}, {type_path_kind: 0; type_argument_index: 0}, {type_path_kind: 0; type_argument_index: 0}]
@F5[{type_path_kind: 3; type_argument_index: 0}, {type_path_kind: 3; type_argument_index: 0}, {type_path_kind: 0; type_argument_index: 0}, {type_path_kind: 0; type_argument_index: 0}, {type_path_kind: 0; type_argument_index: 0}]

Table 4.7.20.2-E. type_path structures for@A Outer . @B Middle . @C Inner

Assuming: 
class Outer {  class Middle {    class Inner {}  }}
Annotationpath_lengthpath
@A0[]
@B1[{type_path_kind: 1; type_argument_index: 0}]
@C2[{type_path_kind: 1; type_argument_index: 0}, {type_path_kind: 1; type_argument_index: 0}]

Table 4.7.20.2-F. type_path structures forOuter . @A MiddleStatic . @B Inner

Assuming: 
class Outer {  static class MiddleStatic {    class Inner {}  }}
Annotationpath_lengthpath
@A0[]
@B1[{type_path_kind: 1; type_argument_index: 0}]
   In the typeOuter . MiddleStatic . Inner, type annotations on the simple nameOuter are not admissible because the type name to its right,MiddleStatic, does not refer to an inner class ofOuter.

Table 4.7.20.2-G. type_path structures forOuter . MiddleStatic . @A InnerStatic

Assuming: 
class Outer {  static class MiddleStatic {    static class InnerStatic {}  }}
Annotationpath_lengthpath
@A0[]
   In the typeOuter . MiddleStatic . InnerStatic, type annotations on the simple nameOuter are not admissible because the type name to its right,MiddleStatic, does not refer to an inner class ofOuter. Similarly, type annotations on the simple nameMiddleStatic are not admissible because the type name to its right,InnerStatic, does not refer to an inner class ofMiddleStatic.

Table 4.7.20.2-H. type_path structures forOuter . Middle<@A Foo . @B Bar> . Inner<@D String @C []>

Assuming: 
class Outer {  class Middle<T> {    class Inner<U> {}  }}
Annotationpath_lengthpath
@A2[{type_path_kind: 1; type_argument_index: 0}, {type_path_kind: 3; type_argument_index: 0}]
@B3[{type_path_kind: 1; type_argument_index: 0}, {type_path_kind: 3; type_argument_index: 0}, {type_path_kind: 1; type_argument_index: 0}]
@C3[{type_path_kind: 1; type_argument_index: 0}, {type_path_kind: 1; type_argument_index: 0}, {type_path_kind: 3; type_argument_index: 0}]
@D4[{type_path_kind: 1; type_argument_index: 0}, {type_path_kind: 1; type_argument_index: 0}, {type_path_kind: 3; type_argument_index: 0}, {type_path_kind: 0; type_argument_index: 0}]

4.7.21. TheRuntimeInvisibleTypeAnnotations Attribute

TheRuntimeInvisibleTypeAnnotations attribute is an variable-length attribute in theattributes table of aClassFile,field_info,method_info, orrecord_component_info structure, orCode attribute (§4.1,§4.5,§4.6,§4.7.30,§4.7.3). TheRuntimeInvisibleTypeAnnotations attribute stores run-time invisible annotations on types used in the corresponding declaration of a class, field, method, or record component, or in an expression in the corresponding method body. TheRuntimeInvisibleTypeAnnotations attribute also stores annotations on type parameter declarations of generic classes, interfaces, methods, and constructors.

There may be at most oneRuntimeInvisibleTypeAnnotations attribute in theattributes table of aClassFile,field_info,method_info, orrecord_component_info structure, orCode attribute.

Anattributes table contains aRuntimeInvisibleTypeAnnotations attribute only if types are annotated in kinds of declaration or expression that correspond to the parent structure or attribute of theattributes table.

TheRuntimeInvisibleTypeAnnotations attribute has the following format:

RuntimeInvisibleTypeAnnotations_attribute {    u2              attribute_name_index;    u4              attribute_length;    u2              num_annotations;    type_annotation annotations[num_annotations];}

The items of theRuntimeInvisibleTypeAnnotations_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure representing the string "RuntimeInvisibleTypeAnnotations".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

num_annotations

The value of thenum_annotations item gives the number of run-time invisible type annotations represented by the structure.

annotations[]

Each entry in theannotations table represents a single run-time invisible annotation on a type used in a declaration or expression. Thetype_annotation structure is specified in§4.7.20.

4.7.22. TheAnnotationDefault Attribute

TheAnnotationDefault attribute is a variable-length attribute in theattributes table of certainmethod_info structures (§4.6), namely those representing elements of annotation interfaces (JLS §9.6.1). TheAnnotationDefault attribute records the default value (JLS §9.6.2) for the element represented by themethod_info structure.

There may be at most oneAnnotationDefault attribute in theattributes table of amethod_info structure which represents an element of an annotation interface.

TheAnnotationDefault attribute has the following format:

AnnotationDefault_attribute {    u2            attribute_name_index;    u4            attribute_length;    element_value default_value;}

The items of theAnnotationDefault_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "AnnotationDefault".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

default_value

Thedefault_value item represents the default value of the annotation interface element represented by themethod_info structure enclosing thisAnnotationDefault attribute.

4.7.23. TheBootstrapMethods Attribute

TheBootstrapMethods attribute is a variable-length attribute in theattributes table of aClassFile structure (§4.1). TheBootstrapMethods attribute records bootstrap methods used to produce dynamically-computed constants and dynamically-computed call sites (§4.4.10).

There must be exactly oneBootstrapMethods attribute in theattributes table of aClassFile structure if theconstant_pool table of theClassFile structure has at least oneCONSTANT_Dynamic_info orCONSTANT_InvokeDynamic_info entry.

There may be at most oneBootstrapMethods attribute in theattributes table of aClassFile structure.

TheBootstrapMethods attribute has the following format:

BootstrapMethods_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 num_bootstrap_methods;    {   u2 bootstrap_method_ref;        u2 num_bootstrap_arguments;        u2 bootstrap_arguments[num_bootstrap_arguments];    } bootstrap_methods[num_bootstrap_methods];}

The items of theBootstrapMethods_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "BootstrapMethods".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

num_bootstrap_methods

The value of thenum_bootstrap_methods item determines the number of bootstrap method specifiers in thebootstrap_methods array.

bootstrap_methods[]

Each entry in thebootstrap_methods table contains an index to aCONSTANT_MethodHandle_info structure which specifies a bootstrap method, and a sequence (perhaps empty) of indexes tostatic arguments for the bootstrap method.

Eachbootstrap_methods entry must contain the following three items:

bootstrap_method_ref

The value of thebootstrap_method_ref item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_MethodHandle_info structure (§4.4.8).

The method handle will be resolved during resolution of a dynamically-computed constant or call site (§5.4.3.6), and then invoked as if by invocation ofinvokeWithArguments injava.lang.invoke.MethodHandle. The method handle must be able to accept the array of arguments described in§5.4.3.6, or resolution will fail.

num_bootstrap_arguments

The value of thenum_bootstrap_arguments item gives the number of items in thebootstrap_arguments array.

bootstrap_arguments[]

Each entry in thebootstrap_arguments array must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be loadable (§4.4).

4.7.24. TheMethodParameters Attribute

TheMethodParameters attribute is a variable-length attribute in theattributes table of amethod_info structure (§4.6). AMethodParameters attribute records information about the formal parameters of a method, such as their names.

There may be at most oneMethodParameters attribute in theattributes table of amethod_info structure.

TheMethodParameters attribute has the following format:

MethodParameters_attribute {    u2 attribute_name_index;    u4 attribute_length;    u1 parameters_count;    {   u2 name_index;        u2 access_flags;    } parameters[parameters_count];}

The items of theMethodParameters_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "MethodParameters".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

parameters_count

The value of theparameters_count item indicates the number of parameter descriptors in the method descriptor (§4.3.3) referenced by thedescriptor_index of the attribute's enclosingmethod_info structure.

This is not a constraint which a Java Virtual Machine implementation must enforce during format checking (§4.8). The task of matching parameter descriptors in a method descriptor against the items in theparameters array below is done by the reflection libraries of the Java SE Platform.

parameters[]

Each entry in theparameters array contains the following pair of items:

name_index

The value of thename_index item must either be zero or a valid index into theconstant_pool table.

If the value of thename_index item is zero, then thisparameters element indicates a formal parameter with no name.

If the value of thename_index item is nonzero, theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure representing a valid unqualified name denoting a formal parameter (§4.2.2).

access_flags

The value of theaccess_flags item is as follows:

0x0010 (ACC_FINAL)

Indicates that the formal parameter was declaredfinal.

0x1000 (ACC_SYNTHETIC)

Indicates that the formal parameter was not explicitly or implicitly declared in source code, according to the specification of the language in which the source code was written (JLS §13.1). (The formal parameter is an implementation artifact of the compiler which produced thisclass file.)

0x8000 (ACC_MANDATED)

Indicates that the formal parameter was implicitly declared in source code, according to the specification of the language in which the source code was written (JLS §13.1). (The formal parameter is mandated by a language specification, so all compilers for the language must emit it.)

Thei'th entry in theparameters array corresponds to thei'th parameter descriptor in the enclosing method's descriptor. (Theparameters_count item is one byte because a method descriptor is limited to 255 parameters.) Effectively, this means theparameters array stores information for all the parameters of the method. One could imagine other schemes, where entries in theparameters array specify their corresponding parameter descriptors, but it would unduly complicate theMethodParameters attribute.

Thei'th entry in theparameters array may or may not correspond to thei'th type in the enclosing method'sSignature attribute (if present), or to thei'th annotation in the enclosing method's parameter annotations.

4.7.25. TheModule Attribute

TheModule attribute is a variable-length attribute in theattributes table of aClassFile structure (§4.1). TheModule attribute indicates the modules required by a module; the packages exported and opened by a module; and the services used and provided by a module.

There may be at most oneModule attribute in theattributes table of aClassFile structure.

TheModule attribute has the following format:

Module_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 module_name_index;    u2 module_flags;    u2 module_version_index;    u2 requires_count;    {   u2 requires_index;        u2 requires_flags;        u2 requires_version_index;    } requires[requires_count];    u2 exports_count;    {   u2 exports_index;        u2 exports_flags;        u2 exports_to_count;        u2 exports_to_index[exports_to_count];    } exports[exports_count];    u2 opens_count;    {   u2 opens_index;        u2 opens_flags;        u2 opens_to_count;        u2 opens_to_index[opens_to_count];    } opens[opens_count];    u2 uses_count;    u2 uses_index[uses_count];    u2 provides_count;    {   u2 provides_index;        u2 provides_with_count;        u2 provides_with_index[provides_with_count];    } provides[provides_count];}

The items of theModule_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "Module".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

module_name_index

The value of themodule_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Module_info structure (§4.4.11) denoting the current module.

module_flags

The value of themodule_flags item is as follows:

0x0020 (ACC_OPEN)

Indicates that this module is open.

0x1000 (ACC_SYNTHETIC)

Indicates that this module was not explicitly or implicitly declared.

0x8000 (ACC_MANDATED)

Indicates that this module was implicitly declared.

module_version_index

The value of themodule_version_index item must be either zero or a valid index into theconstant_pool table. If the value of the item is zero, then no version information about the current module is present. If the value of the item is nonzero, then theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure representing the version of the current module.

requires_count

The value of therequires_count item indicates the number of entries in therequires table.

If the current module isjava.base, thenrequires_count must be zero.

If the current module is notjava.base, thenrequires_count must be at least one.

requires[]

Each entry in therequires table specifies a dependence of the current module. The items in each entry are as follows:

requires_index

The value of therequires_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Module_info structure denoting a module on which the current module depends.

At most one entry in therequires table may specify a module of a given name with itsrequires_index item.

requires_flags

The value of therequires_flags item is as follows:

0x0020 (ACC_TRANSITIVE)

Indicates that any module which depends on the current module, implicitly declares a dependence on the module indicated by this entry.

0x0040 (ACC_STATIC_PHASE)

Indicates that this dependence is mandatory in the static phase, i.e., at compile time, but is optional in the dynamic phase, i.e., at run time.

0x1000 (ACC_SYNTHETIC)

Indicates that this dependence was not explicitly or implicitly declared in the source of the module declaration.

0x8000 (ACC_MANDATED)

Indicates that this dependence was implicitly declared in the source of the module declaration.

requires_version_index

The value of therequires_version_index item must be either zero or a valid index into theconstant_pool table. If the value of the item is zero, then no version information about the dependence is present. If the value of the item is nonzero, then theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure representing the version of the module specified byrequires_index.

Unless the current module isjava.base, exactly one entry in therequires table must have all of the following:

  • Arequires_index item that indicatesjava.base.

  • Arequires_flags item that has theACC_SYNTHETIC flag not set. (TheACC_MANDATED flag may be set.)

  • If theclass file version number is 54.0 or above, arequires_flags item that has both theACC_TRANSITIVE andACC_STATIC_PHASE flags not set.

exports_count

The value of theexports_count item indicates the number of entries in theexports table.

exports[]

Each entry in theexports table specifies a package exported by the current module, such thatpublic andprotected types in the package, and theirpublic andprotected members, may be accessed from outside the current module, possibly from a limited set of "friend" modules.

The items in each entry are as follows:

exports_index

The value of theexports_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Package_info structure (§4.4.12) representing a package exported by the current module.

At most one entry in theexports table may specify a package of a given name with itsexports_index item.

exports_flags

The value of theexports_flags item is as follows:

0x1000 (ACC_SYNTHETIC)

Indicates that this export was not explicitly or implicitly declared in the source of the module declaration.

0x8000 (ACC_MANDATED)

Indicates that this export was implicitly declared in the source of the module declaration.

exports_to_count

The value of theexports_to_count indicates the number of entries in theexports_to_index table.

Ifexports_to_count is zero, then this package is exported by the current module in anunqualified fashion; code in any other module may access the types and members in the package.

Ifexports_to_count is nonzero, then this package is exported by the current module in aqualified fashion; only code in the modules listed in theexports_to_index table may access the types and members in the package.

exports_to_index[]

The value of each entry in theexports_to_index table must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Module_info structure denoting a module whose code can access the types and members in this exported package.

For each entry in theexports table, at most one entry in itsexports_to_index table may specify a module of a given name.

opens_count

The value of theopens_count item indicates the number of entries in theopens table.

opens_count must be zero if the current module is open.

opens[]

Each entry in theopens table specifies a package opened by the current module, such that all types in the package, and all their members, may be accessed from outside the current module via the reflection libraries of the Java SE Platform, possibly from a limited set of "friend" modules.

The items in each entry are as follows:

opens_index

The value of theopens_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Package_info structure representing a package opened by the current module.

At most one entry in theopens table may specify a package of a given name with itsopens_index item.

opens_flags

The value of theopens_flags item is as follows:

0x1000 (ACC_SYNTHETIC)

Indicates that this opening was not explicitly or implicitly declared in the source of the module declaration.

0x8000 (ACC_MANDATED)

Indicates that this opening was implicitly declared in the source of the module declaration.

opens_to_count

The value of theopens_to_count indicates the number of entries in theopens_to_index table.

Ifopens_to_count is zero, then this package is opened by the current module in anunqualified fashion; code in any other module may reflectively access the types and members in the package.

Ifopens_to_count is nonzero, then this package is opened by the current module in aqualified fashion; only code in the modules listed in theopens_to_index table may reflectively access the types and members in the package.

opens_to_index[]

The value of each entry in theopens_to_index table must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Module_info structure denoting a module whose code can access the types and members in this opened package.

For each entry in theopens table, at most one entry in itsopens_to_index table may specify a module of a given name.

uses_count

The value of theuses_count item indicates the number of entries in theuses_index table.

uses_index[]

The value of each entry in theuses_index table must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure (§4.4.1) representing a service interface which the current module may discover viajava.util.ServiceLoader.

At most one entry in theuses_index table may specify a service interface of a given name.

provides_count

The value of theprovides_count item indicates the number of entries in theprovides table.

provides[]

Each entry in theprovides table represents a service implementation for a given service interface.

The items in each entry are as follows:

provides_index

The value of theprovides_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure representing a service interface for which the current module provides a service implementation.

At most one entry in theprovides table may specify a service interface of a given name with itsprovides_index item.

provides_with_count

The value of theprovides_with_count indicates the number of entries in theprovides_with_index table.

provides_with_count must be nonzero.

provides_with_index[]

The value of each entry in theprovides_with_index table must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure representing a service implementation for the service interface specified byprovides_index.

For each entry in theprovides table, at most one entry in itsprovides_with_index table may specify a service implementation of a given name.

4.7.26. TheModulePackages Attribute

TheModulePackages attribute is a variable-length attribute in theattributes table of aClassFile structure (§4.1). TheModulePackages attribute indicates all the packages of a module that are exported or opened by theModule attribute, as well as all the packages of the service implementations recorded in theModule attribute. TheModulePackages attribute may also indicate packages in the module that are neither exported nor opened nor contain service implementations.

There may be at most oneModulePackages attribute in theattributes table of aClassFile structure.

TheModulePackages attribute has the following format:

ModulePackages_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 package_count;    u2 package_index[package_count];}

The items of theModulePackages_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "ModulePackages".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

package_count

The value of thepackage_count item indicates the number of entries in thepackage_index table.

package_index[]

The value of each entry in thepackage_index table must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Package_info structure (§4.4.12) representing a package in the current module.

At most one entry in thepackage_index table may specify a package of a given name.

4.7.27. TheModuleMainClass Attribute

TheModuleMainClass attribute is a fixed-length attribute in theattributes table of aClassFile structure (§4.1). TheModuleMainClass attribute indicates the main class of a module.

There may be at most oneModuleMainClass attribute in theattributes table of aClassFile structure.

TheModuleMainClass attribute has the following format:

ModuleMainClass_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 main_class_index;}

The items of theModuleMainClass_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "ModuleMainClass".

attribute_length

The value of theattribute_length item must be two.

main_class_index

The value of themain_class_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure (§4.4.1) representing the main class of the current module.

4.7.28. TheNestHost Attribute

TheNestHost attribute is a fixed-length attribute in theattributes table of aClassFile structure. TheNestHost attribute records the nest host of the nest to which the current class or interface claims to belong (§5.4.4).

There may be at most oneNestHost attribute in theattributes table of aClassFile structure.

TheNestHost attribute has the following format:

NestHost_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 host_class_index;}

The items of theNestHost_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "NestHost".

attribute_length

The value of theattribute_length item must be two.

host_class_index

The value of thehost_class_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure (§4.4.1) representing a class or interface which is the nest host for the current class or interface.

If the nest host cannot be loaded, or is not in the same run-time package as the current class or interface, or does not authorize nest membership for the current class or interface, then an error may occur during access control (§5.4.4).

4.7.29. TheNestMembers Attribute

TheNestMembers attribute is a variable-length attribute in theattributes table of aClassFile structure (§4.1). TheNestMembers attribute records the classes and interfaces that are authorized to claim membership in the nest hosted by the current class or interface (§5.4.4).

There may be at most oneNestMembers attribute in theattributes table of aClassFile structure.

Theattributes table of aClassFile structure must not contain both aNestMembers attribute and aNestHost attribute.

This rule prevents a nest host from claiming membership in a different nest. It is implicitly a member of the nest that it hosts.

TheNestMembers attribute has the following format:

NestMembers_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 number_of_classes;    u2 classes[number_of_classes];}

The items of theNestMembers_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "NestMembers".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

number_of_classes

The value of thenumber_of_classes item indicates the number of entries in theclasses array.

classes[]

Each value in theclasses array must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure (§4.4.1) representing a class or interface which is a member of the nest hosted by the current class or interface.

Theclasses array is consulted by access control (§5.4.4). It should consist of references to other classes and interfaces that are in the same run-time package and haveNestHost attributes which reference the current class or interface. Array items that do not meet these criteria are ignored by access control.

4.7.30. TheRecord Attribute

TheRecord attribute is a variable-length attribute in theattributes table of aClassFile structure (§4.1). TheRecord attribute indicates that the current class is a record class (JLS §8.10), and stores information about the record components of the record class (JLS §8.10.1).

There may be at most oneRecord attribute in theattributes table of aClassFile structure.

TheRecord attribute has the following format:

Record_attribute {    u2                    attribute_name_index;    u4                    attribute_length;    u2                    components_count;    record_component_info components[components_count];}

The items of theRecord_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "Record".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

components_count

The value of thecomponents_count item indicates the number of entries in thecomponents table.

components[]

Each entry in thecomponents table specifies a record component of the current class, in the order the record components were declared. Therecord_component_info structure has the following format:

record_component_info {    u2             name_index;    u2             descriptor_index;    u2             attributes_count;    attribute_info attributes[attributes_count];}

The items of therecord_component_info structure are as follows:

name_index

The value of thename_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing a valid unqualified name denoting the record component (§4.2.2).

descriptor_index

The value of thedescriptor_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing a field descriptor which encodes the type of the record component (§4.3.2).

attributes_count

The value of theattributes_count item indicates the number of additional attributes of this record component.

attributes[]

Each value of theattributes table must be anattribute_info structure (§4.7).

A record component can have any number of optional attributes associated with it.

The attributes defined by this specification as appearing in theattributes table of arecord_component_info structure are listed inTable 4.7-C.

The rules concerning attributes defined to appear in theattributes table of arecord_component_info structure are given in§4.7.

The rules concerning non-predefined attributes in theattributes table of arecord_component_info structure are given in§4.7.1.

4.7.31. ThePermittedSubclasses Attribute

ThePermittedSubclasses attribute is a variable-length attribute in theattributes table of aClassFile structure (§4.1). ThePermittedSubclasses attribute records the classes and interfaces that are authorized to directly extend or implement the current class or interface (§5.3.5).

The Java programming language uses the modifiersealed to indicate a class or interface that limits its direct subclasses or direct subinterfaces. One might suppose that this modifier would correspond to anACC_SEALED flag in aclass file, since the related modifierfinal corresponds to theACC_FINAL flag. In fact, asealed class or interface is indicated in aclass file by the presence of thePermittedSubclasses attribute.

There may be at most onePermittedSubclasses attribute in theattributes table of aClassFile structure whoseaccess_flags item does not have theACC_FINAL flag set.

There must be noPermittedSubclasses attribute in theattributes table of aClassFile structure whoseaccess_flags item has theACC_FINAL flag set.

sealed is distinct fromfinal: asealed class has a list of authorized subclasses, which afinal class has no subclasses. Thus, aClassFile structure may have aPermittedSubclasses attribute, or have itsACC_FINAL flag set, but not both.

ThePermittedSubclasses attribute has the following format:

PermittedSubclasses_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 number_of_classes;    u2 classes[number_of_classes];}

The items of thePermittedSubclasses_attribute structure are as follows:

attribute_name_index

The value of theattribute_name_index item must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Utf8_info structure (§4.4.7) representing the string "PermittedSubclasses".

attribute_length

The value of theattribute_length item indicates the length of the attribute, excluding the initial six bytes.

number_of_classes

The value of thenumber_of_classes item indicates the number of entries in theclasses array.

classes[]

Each value in theclasses array must be a valid index into theconstant_pool table. Theconstant_pool entry at that index must be aCONSTANT_Class_info structure (§4.4.1) representing a class or interface which is authorized to directly extend or implement the current class or interface.

Theclasses array is consulted when a class or interface is created that attempts to directly extend or implement the current class or interface (§5.3.5). Array items that represent classes or interfaces which do not attempt to directly extend or implement the current class or interface are ignored.

4.8. Format Checking

When a prospectiveclass file is loaded by the Java Virtual Machine (§5.3), the Java Virtual Machine first ensures that the file has the basic format of aclass file (§4.1). This process is known asformat checking. The checks are as follows:

  • The first four bytes must contain the right magic number.

  • All predefined attributes (§4.7) must be of the proper length, except forStackMapTable,RuntimeVisibleAnnotations,RuntimeInvisibleAnnotations,RuntimeVisibleParameterAnnotations,RuntimeInvisibleParameterAnnotations,RuntimeVisibleTypeAnnotations,RuntimeInvisibleTypeAnnotations, andAnnotationDefault.

  • Theclass file must not be truncated or have extra bytes at the end.

  • The constant pool must satisfy the constraints documented throughout§4.4.

    For example, eachCONSTANT_Class_info structure in the constant pool must contain in itsname_index item a valid constant pool index for aCONSTANT_Utf8_info structure.

  • All field references and method references in the constant pool must have valid names, valid classes, and valid descriptors (§4.3).

    Format checking does not ensure that the given field or method actually exists in the given class, nor that the descriptors given refer to real classes. Format checking ensures only that these items are well formed. More detailed checking is performed when the bytecodes themselves are verified, and during resolution.

These checks for basicclass file integrity are necessary for any interpretation of theclass file contents. Format checking is distinct from bytecode verification, although historically they have been confused because both are a form of integrity check.

4.9. Constraints on Java Virtual Machine Code

The code for a method, instance initialization method (§2.9.1), or class or interface initialization method (§2.9.2) is stored in thecode array of theCode attribute of amethod_info structure of aclass file (§4.7.3). This section describes the constraints associated with the contents of theCode_attribute structure.

4.9.1. Static Constraints

Thestatic constraints on aclass 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 theclass file. The static constraints on the code in aclass file specify how Java Virtual Machine instructions must be laid out in thecode array and what the operands of individual instructions must be.

The static constraints on the instructions in thecode array are as follows:

  • Only instances of the instructions documented in§6.5 may appear in thecode array. Instances of instructions using the reserved opcodes (§6.2) or any opcodes not documented in this specification must not appear in thecode array.

    If theclass file version number is 51.0 or above, then instances of instructions using thejsr,jsr_w, orret opcodes must not appear in thecode array.

  • The opcode of the first instruction in thecode array begins at index0.

  • For each instruction in thecode 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.

    Thewide instruction is treated like any other instruction for these purposes; the opcode specifying the operation that awide instruction is to modify is treated as one of the operands of thatwide instruction. That opcode must never be directly reachable by the computation.

  • The last byte of the last instruction in thecode array must be the byte at indexcode_length - 1.

The static constraints on the operands of instructions in thecode 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 awide instruction; a jump or branch target may be thewide instruction itself.

  • Each target, including the default, of eachtableswitch instruction must be the opcode of an instruction within this method.

    Eachtableswitch instruction must have a number of entries in its jump table that is consistent with the value of itslow andhigh jump table operands, and itslow value must be less than or equal to itshigh value.

    No target of atableswitch instruction may be the opcode used to specify the operation to be modified by awide instruction; atableswitch target may be awide instruction itself.

  • Each target, including the default, of eachlookupswitch instruction must be the opcode of an instruction within this method.

    Eachlookupswitch instruction must have a number ofmatch-offset pairs that is consistent with the value of itsnpairs operand. Thematch-offset pairs must be sorted in increasing numerical order by signed match value.

    No target of alookupswitch instruction may be the opcode used to specify the operation to be modified by awide instruction; alookupswitch target may be awide instruction itself.

  • The operands of eachldc instruction and eachldc_w instruction must represent a valid index into theconstant_pool table. The constant pool entry referenced by that index must be loadable (§4.4), and not any of the following:

    • An entry of kindCONSTANT_Long orCONSTANT_Double.

    • An entry of kindCONSTANT_Dynamic that references aCONSTANT_NameAndType_info structure which indicates a descriptor ofJ (denotinglong) orD (denotingdouble).

  • The operands of eachldc2_w instruction must represent a valid index into theconstant_pool table. The constant pool entry referenced by that index must be loadable, and in particular one of the following:

    • An entry of kindCONSTANT_Long orCONSTANT_Double.

    • An entry of kindCONSTANT_Dynamic that references aCONSTANT_NameAndType_info structure which indicates a descriptor ofJ (denotinglong) orD (denotingdouble).

    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 eachgetfield,putfield,getstatic, andputstatic instruction must represent a valid index into theconstant_pool table. The constant pool entry referenced by that index must be of kindCONSTANT_Fieldref.

  • Theindexbyte operands of eachinvokevirtual instruction must represent a valid index into theconstant_pool table. The constant pool entry referenced by that index must be of kindCONSTANT_Methodref.

  • Theindexbyte operands of eachinvokespecial andinvokestatic instruction must represent a valid index into theconstant_pool table. If theclass file version number is less than 52.0, the constant pool entry referenced by that index must be of kindCONSTANT_Methodref; if theclass file version number is 52.0 or above, the constant pool entry referenced by that index must be of kindCONSTANT_Methodref orCONSTANT_InterfaceMethodref.

  • Theindexbyte operands of eachinvokeinterface instruction must represent a valid index into theconstant_pool table. The constant pool entry referenced by that index must be of kindCONSTANT_InterfaceMethodref.

    The value of thecount operand of eachinvokeinterface 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 theCONSTANT_NameAndType_info structure referenced by theCONSTANT_InterfaceMethodref constant pool entry.

    The fourth operand byte of eachinvokeinterface instruction must have the value zero.

  • Theindexbyte operands of eachinvokedynamic instruction must represent a valid index into theconstant_pool table. The constant pool entry referenced by that index must be of kindCONSTANT_InvokeDynamic.

    The third and fourth operand bytes of eachinvokedynamic instruction must have the value zero.

  • Only theinvokespecial instruction is allowed to invoke an instance initialization method (§2.9.1).

    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 eachinstanceof,checkcast,new, andanewarray instruction, and theindexbyte operands of eachmultianewarray instruction, must represent a valid index into theconstant_pool table. The constant pool entry referenced by that index must be of kindCONSTANT_Class.

  • Nonew instruction may reference a constant pool entry of kindCONSTANT_Class that represents an array type (§4.3.2). Thenew instruction cannot be used to create an array.

  • Noanewarray instruction may be used to create an array of more than 255 dimensions.

  • Amultianewarray instruction must be used only to create an array of a type that has at least as many dimensions as the value of itsdimensions operand. That is, while amultianewarray instruction is not required to create all of the dimensions of the array type referenced by itsindexbyte operands, it must not attempt to create more dimensions than are in the array type.

    Thedimensions operand of eachmultianewarray instruction must not be zero.

  • Theatype operand of eachnewarray instruction must take one of the valuesT_BOOLEAN (4),T_CHAR (5),T_FLOAT (6),T_DOUBLE (7),T_BYTE (8),T_SHORT (9),T_INT (10), orT_LONG (11).

  • Theindex operand of eachiload,fload,aload,istore,fstore,astore,iinc, andret instruction must be a non-negative integer no greater thanmax_locals - 1.

    The implicit index of eachiload_<n>,fload_<n>,aload_<n>,istore_<n>,fstore_<n>, andastore_<n> instruction must be no greater thanmax_locals - 1.

  • Theindex operand of eachlload,dload,lstore, anddstore instruction must be no greater thanmax_locals - 2.

    The implicit index of eachlload_<n>,dload_<n>,lstore_<n>, anddstore_<n> instruction must be no greater thanmax_locals - 2.

  • Theindexbyte operands of eachwide instruction modifying aniload,fload,aload,istore,fstore,astore,iinc, orret instruction must represent a non-negative integer no greater thanmax_locals - 1.

    Theindexbyte operands of eachwide instruction modifying anlload,dload,lstore, ordstore instruction must represent a non-negative integer no greater thanmax_locals - 2.

4.9.2. Structural Constraints

The structural constraints on thecode array specify constraints on relationships between Java Virtual Machine instructions. The structural constraints are as follows:

  • Each instruction must only be executed with the appropriate type and number of arguments in the operand stack and local variable array, regardless of the execution path that leads to its invocation.

    As noted in§2.3.4 and§2.11.1, the Java Virtual Machine implicitly converts values of typesboolean,byte,short, andchar to typeint, allowing instructions expecting values of typeint to operate on them.

  • If an instruction can be executed along several different execution paths, the operand stack must have the same depth (§2.6.2) prior to the execution of the instruction, regardless of the path taken.

  • At no point during execution can the operand stack grow to a depth greater than that implied by themax_stack item.

  • At no point during execution can more values be popped from the operand stack than it contains.

  • At no point during execution can the order of the local variable pair holding a value of typelong ordouble be reversed or the pair split up. At no point can the local variables of such a pair be operated on individually.

  • No local variable (or local variable pair, in the case of a value of typelong ordouble) can be accessed before it is assigned a value.

  • Eachinvokespecial instruction must name one of the following:

    • an instance initialization method (§2.9.1)

    • a method in the current class or interface

    • a method in a superclass of the current class

    • a method in a direct superinterface of the current class or interface

    • a method inObject

    If aninvokespecial instruction names an instance initialization method, then the target reference on the operand stack must be an uninitialized class instance. An instance initialization method must never be invoked on an initialized class instance. In addition:

    • If the target reference on the operand stack isan uninitialized class instance for the current class, theninvokespecial must name an instance initialization method from the current class or its direct superclass.

    • If the target reference on the operand stack isa class instance created by an earliernew instruction, theninvokespecial must name an instance initialization method from the class of that class instance.

    • In either case, if the instruction is covered by an exception handler, then any copy of the target reference stored in a local variable must be treated as unusable by the exception handler code.

    If aninvokespecial instruction names a method which is not an instance initialization method, then the target reference on the operand stack must be a class instance whose type is assignment compatible with the current class (JLS §5.2).

    The general rule forinvokespecial is that the class or interface named byinvokespecial must be be "above" the caller class or interface, while the receiver object targeted byinvokespecial must be "at" or "below" the caller class or interface. The latter clause is especially important: a class or interface can only perform invokespecial on its own objects. See§invokespecial for an explanation of how the latter clause is implemented in Prolog.

  • Each instance initialization method, except for the instance initialization method derived from the constructor of classObject, must call either another instance initialization method ofthis or an instance initialization method of its direct superclasssuper before its instance members areaccessed, and before the calling instance initialization method returns.

    However, instance fields ofthis that are declared in the current class may beassigned byputfield before calling any instance initialization method.

  • When any instance method is invoked or when any instance variable is accessed, the class instance that contains the instance method or instance variable must already be initialized.

  • There must never be an uninitialized class instance on the operand stack or in a local variable when ajsr orjsr_w instruction is executed.

  • The type of every class instance that is the target of a method invocation instruction (that is, the type of the target reference on the operand stack) must be assignment compatible with the class or interface type specified in the instruction.

  • The types of the arguments to each method invocation must be method invocation compatible with the method descriptor (JLS §5.3,§4.3.3).

  • Each return instruction must match its method's return type:

    • If the method returns aboolean,byte,char,short, orint, only theireturn instruction may be used.

    • If the method returns afloat,long, ordouble, only anfreturn,lreturn, ordreturn instruction, respectively, may be used.

    • If the method returns areference type, only anareturn instruction may be used, and the type of the returned value must be assignment compatible with the return descriptor of the method (§4.3.3).

    • All instance initialization methods, class or interface initialization methods, and methods declared to returnvoid must use only thereturn instruction.

  • The type of every class instance accessed by agetfield instruction or modified by aputfield instruction (that is, the type of the target reference on the operand stack) must be assignment compatible with the class type specified in the instruction.

  • The type of every value stored by aputfield orputstatic instruction must be compatible with the descriptor of the field (§4.3.2) of the class instance or class being stored into:

    • If the descriptor type isboolean,byte,char,short, orint, then the value must be anint.

    • If the descriptor type isfloat,long, ordouble, then the value must be afloat,long, ordouble, respectively.

    • If the descriptor type is areference type, then the value must be of a type that is assignment compatible with the descriptor type.

  • The type of every value stored into an array by anaastore instruction must be areference type.

    The component type of the array being stored into by theaastore instruction must also be areference type.

  • Eachathrow instruction must throw only values that are instances of classThrowable or of subclasses ofThrowable.

    Each class mentioned in acatch_type item of theexception_table array of the method'sCode_attribute structure must beThrowable or a subclass ofThrowable.

  • Ifgetfield orputfield is used to access aprotected field declared in a superclass that is a member of a different run-time package than the current class, then the type of the class instance being accessed (that is, the type of the target reference on the operand stack) must be assignment compatible with the current class.

    Ifinvokevirtual orinvokespecial is used to access aprotected method declared in a superclass that is a member of a different run-time package than the current class, then the type of the class instance being accessed (that is, the type of the target reference on the operand stack) must be assignment compatible with the current class.

  • Execution never falls off the bottom of thecode array.

  • No return address (a value of typereturnAddress) may be loaded from a local variable.

  • The instruction following eachjsr orjsr_w instruction may be returned to only by a singleret instruction.

  • Nojsr orjsr_w instruction that is returned to may be used to recursively call a subroutine if that subroutine is already present in the subroutine call chain. (Subroutines can be nested when usingtry-finally constructs from within afinally clause.)

  • Each instance of typereturnAddress can be returned to at most once.

    If aret instruction returns to a point in the subroutine call chain above theret instruction corresponding to a given instance of typereturnAddress, then that instance can never be used as a return address.

4.10. Verification ofclass Files

Even though a compiler for the Java programming language must only produceclass files that satisfy all the static and structural constraints in the previous sections, the Java Virtual Machine has no guarantee that any file it is asked to load was generated by that compiler or is properly formed. Applications such as web browsers do not download source code, which they then compile; these applications download already-compiledclass files. The browser needs to determine whether theclass file was produced by a trustworthy compiler or by an adversary attempting to exploit the Java Virtual Machine.

An additional problem with compile-time checking is version skew. A user may have successfully compiled a class, sayPurchaseStockOptions, to be a subclass ofTradingClass. But the definition ofTradingClass might have changed since the time the class was compiled in a way that is not compatible with pre-existing binaries. Methods might have been deleted or had their return types or modifiers changed. Fields might have changed types or changed from instance variables to class variables. The access modifiers of a method or variable may have changed frompublic toprivate. For a discussion of these issues, see Chapter 13, "Binary Compatibility," inThe Java Language Specification, Java SE 24 Edition.

Because of these potential problems, the Java Virtual Machine needs to verify for itself that the desired constraints are satisfied by theclass files it attempts to incorporate. A Java Virtual Machine implementation verifies that eachclass file satisfies the necessary constraints at linking time (§5.4).

Link-time verification enhances the performance of the run-time interpreter. Expensive checks that would otherwise have to be performed to verify constraints at run time for each interpreted instruction can be eliminated. The Java Virtual Machine can assume that these checks have already been performed. For example, the Java Virtual Machine will already know the following:

  • There are no operand stack overflows or underflows.

  • All local variable uses and stores are valid.

  • The arguments to all the Java Virtual Machine instructions are of valid types.

There are two strategies that Java Virtual Machine implementations may use for verification:

  • Verification by type checking must be used to verifyclass files whose version number is greater than or equal to 50.0.

  • Verification by type inference must be supported by all Java Virtual Machine implementations, except those conforming to the Java ME CLDC and Java Card profiles, in order to verifyclass files whose version number is less than 50.0.

    Verification on Java Virtual Machine implementations supporting the Java ME CLDC and Java Card profiles is governed by their respective specifications.

In both strategies, verification is mainly concerned with enforcing the static and structural constraints from§4.9 on thecode array of theCode attribute (§4.7.3). However, there are three additional checks outside theCode attribute which must be performed during verification:

  • Ensuring thatfinal classes are not subclassed.

  • Ensuring thatfinal methods are not overridden (§5.4.5).

  • Checking that every class (exceptObject) has a direct superclass.

4.10.1. Verification by Type Checking

Aclass file whose version number is 50.0 or above (§4.1) must be verified using the type checking rules given in this section.

If, and only if, aclass file's version number equals 50.0, then if the type checking fails, a Java Virtual Machine implementation may choose to attempt to perform verification by type inference (§4.10.2).

This is a pragmatic adjustment, designed to ease the transition to the new verification discipline. Many tools that manipulateclass files may alter the bytecodes of a method in a manner that requires adjustment of the method's stack map frames. If a tool does not make the necessary adjustments to the stack map frames, type checking may fail even though the bytecode is in principle valid (and would consequently verify under the old type inference scheme). To allow implementors time to adapt their tools, Java Virtual Machine implementations may fall back to the older verification discipline, but only for a limited time.

In cases where type checking fails but type inference is invoked and succeeds, a certain performance penalty is expected. Such a penalty is unavoidable. It also should serve as a signal to tool vendors that their output needs to be adjusted, and provides vendors with additional incentive to make these adjustments.

In summary, failover to verification by type inference supports both the gradual addition of stack map frames to the Java SE Platform (if they are not present in a version 50.0class file, failover is allowed) and the gradual removal of thejsr andjsr_w instructions from the Java SE Platform (if they are present in a version 50.0class file, failover is allowed).

If a Java Virtual Machine implementation ever attempts to perform verification by type inference on version 50.0 class files, it must do so in all cases where verification by type checking fails.

This means that a Java Virtual Machine implementation cannot choose to resort to type inference in once case and not in another. It must either rejectclass files that do not verify via type checking, or else consistently failover to the type inferencing verifier whenever type checking fails.

The type checker enforces type rules that are specified by means of Prolog clauses. English language text is used to describe the type rules in an informal way, while the Prolog clauses provide a formal specification.

The type checker requires a list of stack map frames for each method with aCode attribute (§4.7.3). A list of stack map frames is given by theStackMapTable attribute (§4.7.4) of aCode attribute. The intent is that a stack map frame must appear at the beginning of each basic block in a method. The stack map frame specifies the verification type of each operand stack entry and of each local variable at the start of each basic block. The type checker reads the stack map frames for each method with aCode attribute and uses these maps to generate a proof of the type safety of the instructions in theCode attribute.

A class is type safe if all its methods are type safe, and it does not subclass afinal class.

classIsTypeSafe(Class) :-    classClassName(Class, Name),    classDefiningLoader(Class, L),    superclassChain(Name, L, Chain),    Chain \= [],    classSuperClassName(Class, SuperclassName),    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).

The Prolog predicateclassIsTypeSafe assumes thatClass is a Prolog term representing a binary class that has been successfully parsed and loaded. This specification does not mandate the precise structure of this term, but does require that certain predicates be defined upon it.

For example, we assume a predicateclassMethods(Class, Methods) that, given a term representing a class as described above as its first argument, binds its second argument to a list comprising all the methods of the class, represented in a convenient form described later.

Iff the predicateclassIsTypeSafe is not true, the type checker must throw the exceptionVerifyError to indicate that theclass file is malformed. Otherwise, theclass file has type checked successfully and bytecode verification has completed successfully.

The rest of this section explains the process of type checking in detail:

  • First, we give Prolog predicates for core Java Virtual Machine artifacts like classes and methods (§4.10.1.1).

  • Second, we specify the type system known to the type checker (§4.10.1.2).

  • Third, we specify the Prolog representation of instructions and stack map frames (§4.10.1.3,§4.10.1.4).

  • Fourth, we specify how a method is type checked, for methods without code (§4.10.1.5) and methods with code (§4.10.1.6).

  • Fifth, we discuss type checking issues common to all load and store instructions (§4.10.1.7), and also issues of access toprotected members (§4.10.1.8).

  • Finally, we specify the rules to type check each instruction (§4.10.1.9).

4.10.1.1. Accessors for Java Virtual Machine Artifacts

We stipulate the existence of 27 Prolog predicates ("accessors") that have certain expected behavior but whose formal definitions are not given in this specification.

classClassName(Class, ClassName)

Extracts the name,ClassName, of the classClass.

classIsInterface(Class)

True iff the class,Class, is an interface.

classIsNotFinal(Class)

True iff the class,Class, is not afinal class.

classSuperClassName(Class, SuperClassName)

Extracts the name,SuperClassName, of the superclass of classClass.

classInterfaces(Class, Interfaces)

Extracts a list,Interfaces, of the direct superinterfaces of the classClass.

classMethods(Class, Methods)

Extracts a list,Methods, of the methods declared in the classClass.

classDeclaresMember(Class, MemberName, MemberDescriptor)

Asserts that a class,Class, declares a field or method with nameMemberName and descriptorMemberDescriptor. This assertion does not consider members declared in the superclasses or superinterfaces ofClass.

classDefiningLoader(Class, Loader)

Extracts the defining class loader,Loader, of the classClass.

isBootstrapLoader(Loader)

True iff the class loaderLoader is the bootstrap class loader.

loadedClass(Name, InitiatingLoader, ClassDefinition)

True iff there exists a class namedName whose representation (in accordance with this specification) when loaded by the class loaderInitiatingLoader isClassDefinition.

methodName(Method, Name)

Extracts the name,Name, of the methodMethod.

methodAccessFlags(Method, AccessFlags)

Extracts the access flags,AccessFlags, of the methodMethod.

methodDescriptor(Method, Descriptor)

Extracts the descriptor,Descriptor, of the methodMethod.

methodAttributes(Method, Attributes)

Extracts a list,Attributes, of the attributes of the methodMethod.

Each attribute is represented as a functor application of the formattribute(AttributeName, AttributeContents), whereAttributeName is the name of the attribute. The format of the attribute's contents is unspecified.

isInit(Method)

True iffMethod (regardless of class) is<init>.

isNotFinal(Method, Class)

True iffMethod in classClass is notfinal.

isStatic(Method, Class)

True iffMethod in classClass isstatic.

isNotStatic(Method, Class)

True iffMethod in classClass is notstatic.

isPrivate(Method, Class)

True iffMethod in classClass isprivate.

isNotPrivate(Method, Class)

True iffMethod in classClass is notprivate.

isProtected(MemberClass, MemberName, MemberDescriptor)

True iff there is a member namedMemberName with descriptorMemberDescriptor in the classMemberClass and it isprotected.

isNotProtected(MemberClass, MemberName, MemberDescriptor)

True iff there is a member namedMemberName with descriptorMemberDescriptor in the classMemberClass and it is notprotected.

parseFieldDescriptor(Descriptor, Type)

Converts a field descriptor,Descriptor, into the corresponding verification typeType (§4.10.1.2).

parseMethodDescriptor(Descriptor, ArgTypeList, ReturnType)

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.

parseCodeAttribute(Class, Method, FrameSize, MaxStack, ParsedCode, Handlers, StackMap)

Extracts the instruction stream,ParsedCode, of the methodMethod inClass, as well as the maximum operand stack size,MaxStack, the maximal number of local variables,FrameSize, the exception handlers,Handlers, and the stack mapStackMap.

The representation of the instruction stream and stack map attribute must be as specified in§4.10.1.3 and§4.10.1.4.

samePackageName(Class1, Class2)

True iff the package names ofClass1 andClass2 are the same.

differentPackageName(Class1, Class2)

True iff the package names ofClass1 andClass2 are different.

When type checking a method's body, it is convenient to access information about the method. For this purpose, we define anenvironment, a six-tuple consisting of:

  • a class

  • a method

  • the declared return type of the method

  • the instructions in a method

  • the maximal size of the operand stack

  • a list of exception handlers

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).thisClass(Environment, class(ClassName, L)) :-    Environment = environment(Class, _Method, _ReturnType,                              _Instructions, _, _),    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 theclass file. Providing specific accessors to theClass orMethod term would force us to completely specify the format for a Prolog term representing theclass file.

4.10.1.2. Verification Type System

The type checker enforces a type system based upon a hierarchy ofverification types, illustrated below.

Verification type hierarchy:                             top                 ____________/\____________                /                          \               /                            \            oneWord                       twoWord           /   |   \                     /       \          /    |    \                   /         \        int  float  reference        long        double                     /     \                    /       \_____________                   /                      \                  /                        \           uninitialized                    +------------------+            /         \                     |  Java reference  |           /           \                    |  type hierarchy  |uninitializedThis  uninitialized(Offset)    +------------------+                                                     |                                                     |                                                    null

Most verification types have a direct correspondence with the primitive and reference types represented by field descriptors inTable 4.3-A:

  • The primitive typesdouble,float,int, andlong (field descriptorsD,F,I,J) each correspond to the verification type of the same name.

  • The primitive typesbyte,char,short, andboolean (field descriptorsB,C,S,Z) all correspond to the verification typeint.

  • Class and interface types (field descriptors beginningL) correspond to verification types that use the functorclass. The verification typeclass(N,L) represents the class whose binary name isN as loaded by the loaderL. Note thatL is an initiating loader (§5.3) of the class represented byclass(N,L) and may, or may not, be the class's defining loader.

    For example, the class typeObject would be represented asclass('java/lang/Object', BL), whereBL is the bootstrap loader.

  • Array types (field descriptors beginning[) correspond to verification types that use the functorarrayOf. Note that the primitive typesbyte,char,short, andboolean do not correspond to verification types, but an array type whose element type isbyte,char,short, orbooleandoes correspond to a verification type; such verification types support thebaload,bastore,caload,castore,saload,sastore, andnewarray instructions.

    • The verification typearrayOf(T) represents the array type whose component type is the verification typeT.

    • The verification typearrayOf(byte) represents the array type whose element type isbyte.

    • The verification typearrayOf(char) represents the array type whose element type ischar.

    • The verification typearrayOf(short) represents the array type whose element type isshort.

    • The verification typearrayOf(boolean) represents the array type whose element type isboolean.

    For example, the array typesint[] andObject[] would be represented by the verification typesarrayOf(int) andarrayOf(class('java/lang/Object', BL)) respectively. The array typesbyte[] andboolean[][] would be represented by the verification typesarrayOf(byte) andarrayOf(arrayOf(boolean)) respectively.

The remaining verification types are described as follows:

  • The verification typestop,oneWord,twoWord, andreference are represented in Prolog as atoms whose name denotes the verification type in question.

  • The verification typeuninitialized(Offset) is represented by applying the functoruninitialized to an argument representing the numerical value of theOffset.

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 ofX if the direct supertype ofv is a subtype ofX. The rules are:

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(reference, X)   :- isAssignable(oneWord, X).isAssignable(class(_, _), 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).isAssignable(null, class(_, _)).isAssignable(null, arrayOf(_)).isAssignable(null, X) :- isAssignable(class('java/lang/Object', BL), X),                         isBootstrapLoader(BL).

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 language, and rules for the remaining verification types. The split allows us to state general subtyping relations between Java programming language reference types and other verification types. These relations hold independently of a Java reference type's position in the type hierarchy, and help to prevent excessive class loading by a Java Virtual Machine implementation. For example, we do not want to start climbing the Java superclass hierarchy in response to a query of the formclass(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 withisJavaAssignable.

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)).

For assignments, interfaces are treated likeObject.

isJavaAssignable(class(_, _), class(To, L)) :-    loadedClass(To, L, ToClass),    classIsInterface(ToClass).isJavaAssignable(From, To) :-    isJavaSubclassOf(From, To).

Array types are subtypes ofObject. The intent is also that array types are subtypes ofCloneable andjava.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).

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.

isJavaAssignable(arrayOf(X), arrayOf(Y)) :-    compound(X), compound(Y), isJavaAssignable(X, Y).

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).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).

4.10.1.3. Instruction Representation

Individual bytecode instructions are represented in Prolog as terms whose functor is the name of the instruction and whose arguments are its parsed operands.

For example, anaload instruction is represented as the termaload(N), which includes the indexN that is the operand of the instruction.

The instructions as a whole are represented as a list of terms of the form:

instruction(Offset, AnInstruction)

For example,instruction(21, aload(1)).

The order of instructions in this list must be the same as in theclass file.

Some instructions have operands that refer to entries in theconstant_pool table representing fields, methods, and dynamically-computed call sites. Such entries are represented as functor applications of the form:

  • field(FieldClassName, FieldName, FieldDescriptor) for a constant pool entry that is aCONSTANT_Fieldref_info structure (§4.4.2).

    FieldClassName is the name of the class referenced by theclass_index item in the structure.FieldName andFieldDescriptor correspond to the name and field descriptor referenced by thename_and_type_index item of the structure.

  • method(MethodClassName, MethodName, MethodDescriptor) for a constant pool entry that is aCONSTANT_Methodref_info structure (§4.4.2).

    MethodClassName is the name of the class referenced by theclass_index item of the structure.MethodName andMethodDescriptor correspond to the name and method descriptor referenced by thename_and_type_index item of the structure.

  • imethod(MethodIntfName, MethodName, MethodDescriptor) for a constant pool entry that is aCONSTANT_InterfaceMethodref_info structure (§4.4.2).

    MethodIntfName is the name of the interface referenced by theclass_index item of the structure.MethodName andMethodDescriptor correspond to the name and method descriptor referenced by thename_and_type_index item of the structure.

  • dmethod(CallSiteName, MethodDescriptor) for a constant pool entry that is aCONSTANT_InvokeDynamic_info structure (§4.4.10).

    CallSiteName andMethodDescriptor correspond to the name and method descriptor referenced by thename_and_type_index item of the structure. (Thebootstrap_method_attr_index item is irrelevant to verification.)

For clarity, we assume that field and method descriptors (§4.3.2,§4.3.3) are mapped into more readable names: the leadingL and trailing; are dropped from class names, and theBaseType characters used for primitive types are mapped to the names of those types.

For example, agetfield instruction whose operand refers to a constant pool entry representing a fieldfoo of typeF in classBar would be represented asgetfield(field('Bar', 'foo', 'F')).

Theldc instruction, among others, has an operand that refers to aloadable entry in theconstant_pool table. There are nine kinds of loadable entry (seeTable 4.4-C), represented by functor applications of the following forms:

  • int(Value) for a constant pool entry that is aCONSTANT_Integer_info structure (§4.4.4).

    Value is theint constant represented by thebytes item of the structure.

    For example, anldc instruction for loading theint constant 91 would be represented asldc(int(91)).

  • float(Value) for a constant pool entry that is aCONSTANT_Float_info structure (§4.4.4).

    Value is thefloat constant represented by thebytes item of the structure.

  • long(Value) for a constant pool entry that is aCONSTANT_Long_info structure (§4.4.5).

    Value is thelong constant represented by thehigh_bytes andlow_bytes items of the structure.

  • double(Value) for a constant pool entry that is aCONSTANT_Double_info structure (§4.4.5).

    Value is thedouble constant represented by thehigh_bytes andlow_bytes items of the structure.

  • class(ClassName) for a constant pool entry that is aCONSTANT_Class_info structure (§4.4.1).

    ClassName is the name of the class or interface referenced by thename_index item in the structure.

  • string(Value) for a constant pool entry that is aCONSTANT_String_info structure (§4.4.3).

    Value is the string referenced by thestring_index item of the structure.

  • methodHandle(Kind, Reference) for a constant pool entry that is aCONSTANT_MethodHandle_info structure (§4.4.8).

    Kind is the value of thereference_kind item of the structure.Reference is the value of thereference_index item of the structure.

  • methodType(MethodDescriptor) for a constant pool entry that is aCONSTANT_MethodType_info structure (§4.4.9).

    MethodDescriptor is the method descriptor referenced by thedescriptor_index item of the structure.

  • dconstant(ConstantName, FieldDescriptor) for a constant pool entry that is aCONSTANT_Dynamic_info structure (§4.4.10).

    ConstantName andFieldDescriptor correspond to the name and field descriptor referenced by thename_and_type_index item of the structure. (Thebootstrap_method_attr_index item is irrelevant to verification.)

4.10.1.4. Stack Map Frames and Type Transitions

Stack map frames are represented in Prolog as a list of terms of the form:

stackMap(Offset, TypeState)

where:

  • Offset is an integer indicating the bytecode offset at which the stack map frame applies (§4.7.4).

    The order of bytecode offsets in this list must be the same as in theclass file.

  • TypeState is the expected incoming type state for the instruction atOffset.

Atype state is a mapping from locations in the operand stack and local variables of a method to verification types. It has the form:

frame(Locals, OperandStack, Flags)

where:

  • Locals is a list of verification types, such that thei'th element of the list (with 0-based indexing) represents the type of local variablei.

    Types of size 2 (long anddouble) are represented by two local variables (§2.6.1), with the first local variable being the type itself and the second local variable beingtop (§4.10.1.7).

  • OperandStack is a list of verification types, such that the first element of the list represents the type of the top of the operand stack, and the types of stack entries below the top follow in the list in the appropriate order.

    Types of size 2 (long anddouble) are represented by two stack entries, with the first entry beingtop and the second entry being the type itself.

    For example, a stack with adouble value, anint value, and along value is represented in a type state as a stack with five entries:top anddouble entries for thedouble value, anint entry for theint value, andtop andlong entries for thelong value. Accordingly,OperandStack is the list[top, double, int, top, long].

  • Flags is a list which may either be empty or have the single elementflagThisUninit.

    If any local variable inLocals has the typeuninitializedThis, thenFlags has the single elementflagThisUninit, otherwiseFlags is an empty list.

    flagThisUninit is used in constructors to mark type states where initialization ofthis has not yet been completed. In such type states, it is illegal to return from the method.

Subtyping of verification types is extended pointwise to type states. The local variable array of a method has a fixed length by construction (seemethodInitialStackFrame in§4.10.1.6), but the operand stack grows and shrinks, so we require an explicit check on the length of the operand stacks whose assignability is desired for subtyping.

frameIsAssignable(frame(Locals1, StackMap1, Flags1),                  frame(Locals2, StackMap2, Flags2)) :-    length(StackMap1, StackMapLength),    length(StackMap2, StackMapLength),    maplist(isAssignable, Locals1, Locals2),    maplist(isAssignable, StackMap1, StackMap2),    subset(Flags1, Flags2).

Most of the type rules for individual instructions (§4.10.1.9) depend on the notion of a validtype transition. A type transition isvalid if one can pop a list of expected types off the incoming type state's operand stack and replace them with an expected result type, resulting in a new type state where the length of the operand stack does not exceed its declared maximum size.

validTypeTransition(Environment, ExpectedTypesOnStack, ResultType,                    frame(Locals, InputOperandStack, Flags),                    frame(Locals, NextOperandStack, Flags)) :-    popMatchingList(InputOperandStack, ExpectedTypesOnStack,                    InterimOperandStack),    pushOperandStack(InterimOperandStack, ResultType, NextOperandStack),    operandStackHasLegalLength(Environment, NextOperandStack).

Pop a list of types off the stack.

popMatchingList(OperandStack, [], OperandStack).popMatchingList(OperandStack, [P | Rest], NewOperandStack) :-    popMatchingType(OperandStack, P, TempOperandStack, _ActualType),    popMatchingList(TempOperandStack, Rest, NewOperandStack).

Pop an individual type off the stack. The exact behavior depends on the stack contents. If the logical top of the stack is some subtype of the specified type,Type, then pop it. If a type occupies two stack entries, then the logical top of the stack is really the type just below the top, and the top of the stack is the unusable typetop.

popMatchingType([ActualType | OperandStack],                Type, OperandStack, ActualType) :-    sizeOf(Type, 1),    isAssignable(ActualType, Type).popMatchingType([top, ActualType | OperandStack],                Type, OperandStack, ActualType) :-    sizeOf(Type, 2),    isAssignable(ActualType, Type).sizeOf(X, 2) :- isAssignable(X, twoWord).sizeOf(X, 1) :- isAssignable(X, oneWord).sizeOf(top, 1).

Push a logical type onto the stack. The exact behavior varies with the size of the type. If the pushed type is of size 1, we just push it onto the stack. If the pushed type is of size 2, we push it, and then pushtop.

pushOperandStack(OperandStack, 'void', OperandStack).pushOperandStack(OperandStack, Type, [Type | OperandStack]) :-    sizeOf(Type, 1).pushOperandStack(OperandStack, Type, [top, Type | OperandStack]) :-    sizeOf(Type, 2).

The length of the operand stack must not exceed the declared maximum size.

operandStackHasLegalLength(Environment, OperandStack) :-    length(OperandStack, Length),    maxOperandStackLength(Environment, MaxStack),    Length =< MaxStack.

Thedup instructions pop expected types off the incoming type state's operand stack and replace them with predefined result types, resulting in a new type state. However, these instructions are not defined in terms of type transitions because there is no need to match types by means of the subtyping relation. Instead, thedup instructions manipulate the operand stack entirely in terms of thecategory of types on the stack (§2.11.1).

Category 1 types occupy a single stack entry. Popping a logical type of category 1,Type, off the stack is possible if the top of the stack isType andType is nottop (otherwise it could denote the upper half of a category 2 type). The result is the incoming stack, with the top entry popped off.

popCategory1([Type | Rest], Type, Rest) :-    Type \= top,    sizeOf(Type, 1).

Category 2 types occupy two stack entries. Popping a logical type of category 2,Type, off the stack is possible if the top of the stack is typetop, and the entry directly below it isType. The result is the incoming stack, with the top two entries popped off.

popCategory2([top, Type | Rest], Type, Rest) :-    sizeOf(Type, 2).

Thedup instructions push a list of types onto the stack in essentially the same way as when a type is pushed for a valid type transition.

canSafelyPush(Environment, InputOperandStack, Type, OutputOperandStack) :-    pushOperandStack(InputOperandStack, Type, OutputOperandStack),    operandStackHasLegalLength(Environment, OutputOperandStack).canSafelyPushList(Environment, InputOperandStack, Types,                  OutputOperandStack) :-    canPushList(InputOperandStack, Types, OutputOperandStack),    operandStackHasLegalLength(Environment, OutputOperandStack).canPushList(InputOperandStack, [], InputOperandStack).canPushList(InputOperandStack, [Type | Rest], OutputOperandStack) :-    pushOperandStack(InputOperandStack, Type, InterimOperandStack),    canPushList(InterimOperandStack, Rest, OutputOperandStack).

Many of the type rules for individual instructions use the following clause to easily pop a list of types off the stack.

canPop(frame(Locals, OperandStack, Flags), Types,       frame(Locals, PoppedOperandStack, Flags)) :-    popMatchingList(OperandStack, Types, PoppedOperandStack).

Finally, certain array instructions (§aaload,§arraylength,§baload,§bastore) peek at types on the operand stack in order to check they are array types. The following clause accesses thei'th element of the operand stack from a type state.

nth1OperandStackIs(i, frame(_Locals, OperandStack, _Flags), Element) :-    nth1(i, OperandStack, Element).

4.10.1.5. Type Checking Abstract and Native Methods

abstract methods andnative methods are considered to be type safe if they do not override afinal method.

methodIsTypeSafe(Class, Method) :-    doesNotOverrideFinalMethod(Class, Method),    methodAccessFlags(Method, AccessFlags),    member(abstract, AccessFlags).methodIsTypeSafe(Class, Method) :-    doesNotOverrideFinalMethod(Class, Method),    methodAccessFlags(Method, AccessFlags),    member(native, AccessFlags).

private methods andstatic methods are orthogonal to dynamic method dispatch, so they never override other methods (§5.4.5).

doesNotOverrideFinalMethod(class('java/lang/Object', L), Method) :-    isBootstrapLoader(L).doesNotOverrideFinalMethod(Class, Method) :-    isPrivate(Method, Class).doesNotOverrideFinalMethod(Class, Method) :-    isStatic(Method, Class).doesNotOverrideFinalMethod(Class, Method) :-    isNotPrivate(Method, Class),    isNotStatic(Method, Class),    doesNotOverrideFinalMethodOfSuperclass(Class, Method).doesNotOverrideFinalMethodOfSuperclass(Class, Method) :-    classSuperClassName(Class, SuperclassName),    classDefiningLoader(Class, L),    loadedClass(SuperclassName, L, Superclass),    classMethods(Superclass, SuperMethodList),    finalMethodNotOverridden(Method, Superclass, SuperMethodList).

final methods that areprivate and/orstatic are unusual, asprivate methods andstatic methods cannot be overridden per se. Therefore, if afinalprivate method or afinalstatic method is found, it was logically not overridden by another method.

finalMethodNotOverridden(Method, Superclass, SuperMethodList) :-    methodName(Method, Name),    methodDescriptor(Method, Descriptor),    member(method(_, Name, Descriptor), SuperMethodList),    isFinal(Method, Superclass),    isPrivate(Method, Superclass).finalMethodNotOverridden(Method, Superclass, SuperMethodList) :-    methodName(Method, Name),    methodDescriptor(Method, Descriptor),    member(method(_, Name, Descriptor), SuperMethodList),    isFinal(Method, Superclass),    isStatic(Method, Superclass).

If a non-finalprivate method or a non-finalstatic method is found, skip over it because it is orthogonal to overriding.

finalMethodNotOverridden(Method, Superclass, SuperMethodList) :-    methodName(Method, Name),    methodDescriptor(Method, Descriptor),    member(method(_, Name, Descriptor), SuperMethodList),    isNotFinal(Method, Superclass),    isPrivate(Method, Superclass),    doesNotOverrideFinalMethodOfSuperclass(Superclass, Method).finalMethodNotOverridden(Method, Superclass, SuperMethodList) :-    methodName(Method, Name),    methodDescriptor(Method, Descriptor),    member(method(_, Name, Descriptor), SuperMethodList),    isNotFinal(Method, Superclass),    isStatic(Method, Superclass),    doesNotOverrideFinalMethodOfSuperclass(Superclass, Method).

If a non-final, non-private, non-static method is found, then indeed afinal method was not overridden. Otherwise, recurse upwards.

finalMethodNotOverridden(Method, Superclass, SuperMethodList) :-    methodName(Method, Name),    methodDescriptor(Method, Descriptor),    member(method(_, Name, Descriptor), SuperMethodList),    isNotFinal(Method, Superclass),    isNotStatic(Method, Superclass),    isNotPrivate(Method, Superclass).finalMethodNotOverridden(Method, Superclass, SuperMethodList) :-    methodName(Method, Name),    methodDescriptor(Method, Descriptor),    notMember(method(_, Name, Descriptor), SuperMethodList),    doesNotOverrideFinalMethodOfSuperclass(Superclass, Method).

4.10.1.6. Type Checking Methods with Code

Non-abstract, non-native methods are type correct if they have code and the code is type correct.

methodIsTypeSafe(Class, Method) :-    doesNotOverrideFinalMethod(Class, Method),    methodAccessFlags(Method, AccessFlags),    methodAttributes(Method, Attributes),    notMember(native, AccessFlags),    notMember(abstract, AccessFlags),    member(attribute('Code', _), Attributes),    methodWithCodeIsTypeSafe(Class, Method).

A method with code is type safe if it is possible to merge the code and the stack map frames into a single stream such that each stack map frame precedes the instruction it corresponds to, and the merged stream is type correct. The method's exception handlers, if any, must also be legal.

methodWithCodeIsTypeSafe(Class, Method) :-    parseCodeAttribute(Class, Method, FrameSize, MaxStack,                       ParsedCode, Handlers, StackMap),    mergeStackMapAndCode(StackMap, ParsedCode, MergedCode),    methodInitialStackFrame(Class, Method, FrameSize, StackFrame, ReturnType),    Environment = environment(Class, Method, ReturnType, MergedCode,                              MaxStack, Handlers),    handlersAreLegal(Environment),    mergedCodeIsTypeSafe(Environment, MergedCode, StackFrame).

Let us consider exception handlers first.

An exception handler is represented by a functor application of the form:

handler(Start, End, Target, ClassName)

whose arguments are, respectively, the start and end of the range of instructions covered by the handler, the first instruction of the handler code, and the name of the exception class that this handler is designed to handle.

An exception handler islegal if its start (Start) is less than its end (End), there exists an instruction whose offset is equal toStart, there exists an instruction whose offset equalsEnd, and the handler's exception class is assignable to the classThrowable. The exception class of a handler isThrowable if the handler's class entry is 0, otherwise it is the class named in the handler.

handlersAreLegal(Environment) :-    exceptionHandlers(Environment, Handlers),    checklist(handlerIsLegal(Environment), Handlers).handlerIsLegal(Environment, Handler) :-    Handler = handler(Start, End, Target, _),    Start < End,    allInstructions(Environment, Instructions),    member(instruction(Start, _), Instructions),    offsetStackFrame(Environment, Target, _),    instructionsIncludeEnd(Instructions, End),    currentClassLoader(Environment, CurrentLoader),    handlerExceptionClass(Handler, ExceptionClass, CurrentLoader),    isBootstrapLoader(BL),    isAssignable(ExceptionClass, class('java/lang/Throwable', BL)).instructionsIncludeEnd(Instructions, End) :-    member(instruction(End, _), Instructions).instructionsIncludeEnd(Instructions, End) :-    member(endOfCode(End), Instructions).handlerExceptionClass(handler(_, _, _, 0),                      class('java/lang/Throwable', BL), _) :-    isBootstrapLoader(BL).handlerExceptionClass(handler(_, _, _, Name),                      class(Name, L), L) :-    Name \= 0.

Let us now turn to the stream of instructions and stack map frames.

Merging instructions and stack map frames into a single stream involves four cases:

  • Merging an emptyStackMap and a list of instructions yields the original list of instructions.

    mergeStackMapAndCode([], CodeList, CodeList).
  • Given a list of stack map frames beginning with the type state for the instruction atOffset, and a list of instructions beginning atOffset, the merged list is the head of the stack map frame list, followed by the head of the instruction list, followed by the merge of the tails of the two lists.

    mergeStackMapAndCode([stackMap(Offset, Map) | RestMap],                     [instruction(Offset, Parse) | RestCode],                     [stackMap(Offset, Map),                       instruction(Offset, Parse) | RestMerge]) :-    mergeStackMapAndCode(RestMap, RestCode, RestMerge).
  • Otherwise, given a list of stack map frames beginning with the type state for the instruction atOffsetM, and a list of instructions beginning atOffsetP, then, ifOffsetP < OffsetM, the merged list consists of the head of the instruction list, followed by the merge of the stack map frame list and the tail of the instruction list.

    mergeStackMapAndCode([stackMap(OffsetM, Map) | RestMap],                     [instruction(OffsetP, Parse) | RestCode],                     [instruction(OffsetP, Parse) | RestMerge]) :-    OffsetP < OffsetM,    mergeStackMapAndCode([stackMap(OffsetM, Map) | RestMap],                         RestCode, RestMerge).
  • Otherwise, the merge of the two lists is undefined. Since the instruction list has monotonically increasing offsets, the merge of the two lists is not defined unless every stack map frame offset has a corresponding instruction offset and the stack map frames are in monotonically increasing order.

To determine if the merged stream for a method is type correct, we first infer the method's initial type state.

The initial type state of a method consists of an empty operand stack and local variable types derived from the type ofthis and the arguments, as well as the appropriate flag, depending on whether this is an<init> method.

methodInitialStackFrame(Class, Method, FrameSize, frame(Locals, [], Flags),                        ReturnType):-    methodDescriptor(Method, Descriptor),    parseMethodDescriptor(Descriptor, RawArgs, ReturnType),    expandTypeList(RawArgs, Args),    methodInitialThisType(Class, Method, ThisList),    flags(ThisList, Flags),    append(ThisList, Args, ThisArgs),    expandToLength(ThisArgs, FrameSize, top, Locals).

Given a list of types, the following clause produces a list where every type of size 2 has been substituted by two entries: one for itself, and onetop entry. The result then corresponds to the representation of the list as 32-bit words in the Java Virtual Machine.

expandTypeList([], []).expandTypeList([Item | List], [Item | Result]) :-    sizeOf(Item, 1),    expandTypeList(List, Result).expandTypeList([Item | List], [Item, top | Result]) :-    sizeOf(Item, 2),    expandTypeList(List, Result).
flags([uninitializedThis], [flagThisUninit]).flags(X, []) :- X \= [uninitializedThis].expandToLength(List, Size, _Filler, List) :-    length(List, Size).expandToLength(List, Size, Filler, Result) :-    length(List, ListLength),    ListLength < Size,    Delta is Size - ListLength,    length(Extra, Delta),    checklist(=(Filler), Extra),    append(List, Extra, Result).

For the initial type state of an instance method, we compute the type ofthis and put it in a list. The type ofthis in the<init> method ofObject isObject; in other<init> methods, the type ofthis isuninitializedThis; otherwise, the type ofthis in an instance method isclass(N, L) whereN is the name of the class containing the method andL is its defining class loader.

For the initial type state of a static method,this is irrelevant, so the list is empty.

methodInitialThisType(_Class, Method, []) :-    methodAccessFlags(Method, AccessFlags),    member(static, AccessFlags),    methodName(Method, MethodName),    MethodName \= '<init>'.methodInitialThisType(Class, Method, [This]) :-    methodAccessFlags(Method, AccessFlags),    notMember(static, AccessFlags),    instanceMethodInitialThisType(Class, Method, This).instanceMethodInitialThisType(Class, Method, class('java/lang/Object', L)) :-    methodName(Method, '<init>'),    classDefiningLoader(Class, L),    isBootstrapLoader(L),    classClassName(Class, 'java/lang/Object').instanceMethodInitialThisType(Class, Method, uninitializedThis) :-    methodName(Method, '<init>'),    classClassName(Class, ClassName),    classDefiningLoader(Class, CurrentLoader),    superclassChain(ClassName, CurrentLoader, Chain),    Chain \= [].instanceMethodInitialThisType(Class, Method, class(ClassName, L)) :-    methodName(Method, MethodName),    MethodName \= '<init>',    classDefiningLoader(Class, L),    classClassName(Class, ClassName).

We now compute whether the merged stream for a method is type correct, using the method's initial type state:

  • If we have a stack map frame and an incoming type state, the type state must be assignable to the one in the stack map frame. We may then proceed to type check the rest of the stream with the type state given in the stack map frame.

    mergedCodeIsTypeSafe(Environment, [stackMap(Offset, MapFrame) | MoreCode],                     frame(Locals, OperandStack, Flags)) :-    frameIsAssignable(frame(Locals, OperandStack, Flags), MapFrame),    mergedCodeIsTypeSafe(Environment, MoreCode, MapFrame).
  • A merged code stream is type safe relative to an incoming type stateT if it begins with an instructionI that is type safe relative toT, andIsatisfies its exception handlers (see below), and the tail of the stream is type safe given the type state following that execution ofI.

    NextStackFrame indicates what falls through to the following instruction. For an unconditional branch instruction, it will have the special valueafterGoto.ExceptionStackFrame indicates what is passed to exception handlers.

    mergedCodeIsTypeSafe(Environment, [instruction(Offset, Parse) | MoreCode],                     frame(Locals, OperandStack, Flags)) :-    instructionIsTypeSafe(Parse, Environment, Offset,                          frame(Locals, OperandStack, Flags),                          NextStackFrame, ExceptionStackFrame),    instructionSatisfiesHandlers(Environment, Offset, ExceptionStackFrame),    mergedCodeIsTypeSafe(Environment, MoreCode, NextStackFrame).
  • After an unconditional branch (indicated by an incoming type state ofafterGoto), if we have a stack map frame giving the type state for the following instructions, we can proceed and type check them using the type state provided by the stack map frame.

    mergedCodeIsTypeSafe(Environment, [stackMap(Offset, MapFrame) | MoreCode],                     afterGoto) :-    mergedCodeIsTypeSafe(Environment, MoreCode, MapFrame).
  • It is illegal to have code after an unconditional branch without a stack map frame being provided for it.

    mergedCodeIsTypeSafe(_Environment, [instruction(_, _) | _MoreCode],                     afterGoto) :-    write_ln('No stack frame after unconditional branch'),    fail.
  • If we have an unconditional branch at the end of the code, stop.

    mergedCodeIsTypeSafe(_Environment, [endOfCode(Offset)],                     afterGoto).

Branching to a target is type safe if the target has an associated stack frame,Frame, and the current stack frame,StackFrame, is assignable toFrame.

targetIsTypeSafe(Environment, StackFrame, Target) :-    offsetStackFrame(Environment, Target, Frame),    frameIsAssignable(StackFrame, Frame).

An instructionsatisfies its exception handlers if it satisfies every exception handler that is applicable to the instruction.

instructionSatisfiesHandlers(Environment, Offset, ExceptionStackFrame) :-    exceptionHandlers(Environment, Handlers),    sublist(isApplicableHandler(Offset), Handlers, ApplicableHandlers),    checklist(instructionSatisfiesHandler(Environment, ExceptionStackFrame),              ApplicableHandlers).

An exception handler isapplicable to an instruction if the offset of the instruction is greater or equal to the start of the handler's range and less than the end of the handler's range.

isApplicableHandler(Offset, handler(Start, End, _Target, _ClassName)) :-    Offset >= Start,    Offset < End.

An instructionsatisfies an exception handler if the instructions's outgoing type state isExcStackFrame, and the handler's target (the initial instruction of the handler code) is type safe assuming an incoming type stateT. The type stateT is derived fromExcStackFrame by replacing the operand stack with a stack whose sole element is the handler's exception class.

instructionSatisfiesHandler(Environment, ExcStackFrame, Handler) :-    Handler = handler(_, _, Target, _),    currentClassLoader(Environment, CurrentLoader),    handlerExceptionClass(Handler, ExceptionClass, CurrentLoader),    /* The stack consists of just the exception. */    ExcStackFrame = frame(Locals, _, Flags),    TrueExcStackFrame = frame(Locals, [ ExceptionClass ], Flags),    operandStackHasLegalLength(Environment, TrueExcStackFrame),    targetIsTypeSafe(Environment, TrueExcStackFrame, Target).

4.10.1.7. Type Checking Load and Store Instructions

All load instructions are variations on a common pattern, varying the type of the value that the instruction loads.

Loading a value of typeType from local variableIndex is type safe, if the type of that local variable isActualType,ActualType is assignable toType, and pushingActualType onto the incoming operand stack is a valid type transition (§4.10.1.4) that yields a new type stateNextStackFrame. After execution of the load instruction, the type state will beNextStackFrame.

loadIsTypeSafe(Environment, Index, Type, StackFrame, NextStackFrame) :-    StackFrame = frame(Locals, _OperandStack, _Flags),    nth0(Index, Locals, ActualType),    isAssignable(ActualType, Type),    validTypeTransition(Environment, [], ActualType, StackFrame,                        NextStackFrame).

All store instructions are variations on a common pattern, varying the type of the value that the instruction stores.

In general, a store instruction is type safe if the local variable it references is of a type that is a supertype ofType, and the top of the operand stack is of a subtype ofType, whereType is the type the instruction is designed to store.

More precisely, the store is type safe if one can pop a typeActualType that "matches"Type (that is, is a subtype ofType) off the operand stack (§4.10.1.4), and then legally assign that type the local variableLIndex.

storeIsTypeSafe(_Environment, Index, Type,                frame(Locals, OperandStack, Flags),                frame(NextLocals, NextOperandStack, Flags)) :-    popMatchingType(OperandStack, Type, NextOperandStack, ActualType),    modifyLocalVariable(Index, ActualType, Locals, NextLocals).

Given local variablesLocals, modifyingIndex to have typeType results in the local variable listNewLocals. The modifications are somewhat involved, because some values (and their corresponding types) occupy two local variables. Hence, modifyingLN may require modifyingLN+1 (because the type will occupy both theN andN+1 slots) orLN-1 (because localN used to be the upper half of the two word value/type starting at localN-1, and so localN-1 must be invalidated), or both. This is described further below. We start atL0 and count up.

modifyLocalVariable(Index, Type, Locals, NewLocals) :-    modifyLocalVariable(0, Index, Type, Locals, NewLocals).

GivenLocalsRest, the suffix of the local variable list starting at indexI, modifying local variableIndex to have typeType results in the local variable list suffixNextLocalsRest.

IfI < Index-1, just copy the input to the output and recurse forward. IfI = Index-1, the type of localI may change. This can occur ifLI has a type of size 2. Once we setLI+1 to the new type (and the corresponding value), the type/value ofLI will be invalidated, as its upper half will be trashed. Then we recurse forward.

modifyLocalVariable(I, Index, Type,                    [Locals1 | LocalsRest],                    [Locals1 | NextLocalsRest] ) :-    I < Index - 1,    I1 is I + 1,    modifyLocalVariable(I1, Index, Type, LocalsRest, NextLocalsRest).modifyLocalVariable(I, Index, Type,                    [Locals1 | LocalsRest],                    [NextLocals1 | NextLocalsRest] ) :-    I =:= Index - 1,    modifyPreIndexVariable(Locals1, NextLocals1),    modifyLocalVariable(Index, Index, Type, LocalsRest, NextLocalsRest).

When we find the variable, and it only occupies one word, we change it toType and we're done. When we find the variable, and it occupies two words, we change its type toType and the next word totop.

modifyLocalVariable(Index, Index, Type,                    [_ | LocalsRest], [Type | LocalsRest]) :-    sizeOf(Type, 1).modifyLocalVariable(Index, Index, Type,                    [_, _ | LocalsRest], [Type, top | LocalsRest]) :-    sizeOf(Type, 2).

We refer to a local whose index immediately precedes a local whose type will be modified as apre-index variable. The future type of a pre-index variable of typeInputType isResult. If the type,Type, of the pre-index local is of size 1, it doesn't change. If the type of the pre-index local,Type, is 2, we need to mark the lower half of its two word value as unusable, by setting its type totop.

modifyPreIndexVariable(Type, Type) :- sizeOf(Type, 1).modifyPreIndexVariable(Type, top) :- sizeOf(Type, 2).

4.10.1.8. Type Checking forprotected Members

All instructions that access members must contend with the rules concerningprotected members. This section describes theprotected check that corresponds to JLS §6.6.2.1.

Theprotected check applies only toprotected 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, MemberClassName, MemberName,                     MemberDescriptor, StackFrame) :-    thisClass(Environment, class(CurrentClassName, CurrentLoader)),    superclassChain(CurrentClassName, CurrentLoader, Chain),    notMember(class(MemberClassName, _), Chain).
  • If theMemberClassName is the same as the name of a superclass, the class being resolved may indeed be a superclass. In this case, if no superclass namedMemberClassName in a different run-time package has aprotected member namedMemberName with descriptorMemberDescriptor, theprotected 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 notprotected 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, MemberClassName, MemberName,                     MemberDescriptor, StackFrame) :-    thisClass(Environment, class(CurrentClassName, CurrentLoader)),    superclassChain(CurrentClassName, CurrentLoader, Chain),    member(class(MemberClassName, _), Chain),    classesInOtherPkgWithProtectedMember(      class(CurrentClassName, CurrentLoader),      MemberName, MemberDescriptor, MemberClassName, Chain, []).
  • If there does exist aprotected superclass member in a different run-time package, then loadMemberClassName; if the member in question is notprotected, the check does not apply. (Using a superclass member that is notprotected is trivially correct.)

    passesProtectedCheck(Environment, MemberClassName, MemberName,                     MemberDescriptor,                     frame(_Locals, [Target | Rest], _Flags)) :-    thisClass(Environment, class(CurrentClassName, CurrentLoader)),    superclassChain(CurrentClassName, CurrentLoader, Chain),    member(class(MemberClassName, _), Chain),    classesInOtherPkgWithProtectedMember(      class(CurrentClassName, CurrentLoader),      MemberName, MemberDescriptor, MemberClassName, Chain, List),    List \= [],    loadedClass(MemberClassName, CurrentLoader, ReferencedClass),    isNotProtected(ReferencedClass, MemberName, MemberDescriptor).
  • Otherwise, use of a member of an object of typeTarget requires thatTarget be assignable to the type of the current class.

    passesProtectedCheck(Environment, MemberClassName, MemberName,                     MemberDescriptor,                     frame(_Locals, [Target | Rest], _Flags)) :-    thisClass(Environment, class(CurrentClassName, CurrentLoader)),    superclassChain(CurrentClassName, CurrentLoader, Chain),    member(class(MemberClassName, _), Chain),    classesInOtherPkgWithProtectedMember(      class(CurrentClassName, CurrentLoader),      MemberName, MemberDescriptor, MemberClassName, Chain, List),    List \= [],    loadedClass(MemberClassName, CurrentLoader, ReferencedClass),    isProtected(ReferencedClass, MemberName, MemberDescriptor),    isAssignable(Target, class(CurrentClassName, CurrentLoader)).

The predicateclassesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName, Chain, List) is true ifList is the set of classes inChain with nameMemberClassName that are in a different run-time package thanClass which have aprotected member namedMemberName with descriptorMemberDescriptor.

classesInOtherPkgWithProtectedMember(_, _, _, _, [], []).classesInOtherPkgWithProtectedMember(Class, MemberName,                                     MemberDescriptor, MemberClassName,                                     [class(MemberClassName, L) | Tail],                                     [class(MemberClassName, L) | T]) :-    differentRuntimePackage(Class, class(MemberClassName, L)),    loadedClass(MemberClassName, L, Super),    isProtected(Super, MemberName, MemberDescriptor),    classesInOtherPkgWithProtectedMember(      Class, MemberName, MemberDescriptor, MemberClassName, Tail, T).classesInOtherPkgWithProtectedMember(Class, MemberName,                                     MemberDescriptor, MemberClassName,                                     [class(MemberClassName, L) | Tail],                                     T) :-    differentRuntimePackage(Class, class(MemberClassName, L)),    loadedClass(MemberClassName, L, Super),    isNotProtected(Super, MemberName, MemberDescriptor),    classesInOtherPkgWithProtectedMember(      Class, MemberName, MemberDescriptor, MemberClassName, Tail, T).classesInOtherPkgWithProtectedMember(Class, MemberName,                                     MemberDescriptor, MemberClassName,                                     [class(MemberClassName, L) | Tail],                                     T] :-    sameRuntimePackage(Class, class(MemberClassName, L)),    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).

4.10.1.9. Type Checking Instructions

In general, the type rule for an instruction is given relative to an environmentEnvironment that defines the class and method in which the instruction occurs (§4.10.1.1), and the offsetOffset within the method at which the instruction occurs. The rule states that if the incoming type stateStackFrame fulfills certain requirements, then:

  • The instruction is type safe.

  • It is provable that the type state after the instruction completes normally has a particular form given byNextStackFrame, and that the type state after the instruction completes abruptly is given byExceptionStackFrame.

    The type state after an instruction completes abruptly is the same as the incoming type state, except that the operand stack is empty.

    exceptionStackFrame(StackFrame, ExceptionStackFrame) :-    StackFrame = frame(Locals, _OperandStack, Flags),    ExceptionStackFrame = frame(Locals, [], Flags).

Many instructions have type rules that are completely isomorphic to the rules for other instructions. If an instructionb1 is isomorphic to another instructionb2, then the type rule forb1 is the same as the type rule forb2.

instructionIsTypeSafe(Instruction, Environment, Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    instructionHasEquivalentTypeRule(Instruction, IsomorphicInstruction),    instructionIsTypeSafe(IsomorphicInstruction, Environment, Offset,                          StackFrame, NextStackFrame,                          ExceptionStackFrame).

The English language description of each rule is intended to be readable, intuitive, and concise. As such, the description avoids repeating all the contextual assumptions given above. In particular:

  • The description does not explicitly mention the environment.

  • When the description speaks of the operand stack or local variables in the following, it is referring to the operand stack and local variable components of a type state: either the incoming type state or the outgoing one.

  • The type state after the instruction completes abruptly is almost always identical to the incoming type state. The description only discusses the type state after the instruction completes abruptly when that is not the case.

  • The description speaks of popping and pushing types onto the operand stack, and does not explicitly discuss issues of stack underflow or overflow. The description assumes these operations can be completed successfully, but the Prolog clauses for operand stack manipulation ensure that the necessary checks are made.

  • The description discusses only the manipulation of logical types. In practice, some types take more than one word. The description abstracts from these representation details, but the Prolog clauses that manipulate data do not.

Any ambiguities can be resolved by referring to the formal Prolog clauses.

aaload

Anaaload instruction is type safe iff one can validly replace types matchingint and an array type with component typeComponentType whereComponentType is a subtype ofObject, withComponentType 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(class('java/lang/Object', BL))],                        ComponentType, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The component type of an array ofX isX. We define the component type ofnull to benull.

arrayComponentType(arrayOf(X), X).arrayComponentType(null, null).
aastore

Anaastore instruction is type safe iff one can validly pop types matchingObject,int, and an array ofObject off the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(aastore, _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    isBootstrapLoader(BL),    canPop(StackFrame,           [class('java/lang/Object', BL),            int,            arrayOf(class('java/lang/Object', BL))],           NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
aconst_null

Anaconst_null instruction is type safe if one can validly push the typenull onto the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(aconst_null, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [], null, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
aload,aload_<n>

Anaload instruction with operandIndex is type safe and yields an outgoing type stateNextStackFrame, if a load instruction with operandIndex and typereference is type safe and yields an outgoing type stateNextStackFrame.

instructionIsTypeSafe(aload(Index), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    loadIsTypeSafe(Environment, Index, reference, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The instructionsaload_<n>, for 0n 3, are type safe iff the equivalentaload instruction is type safe.

instructionHasEquivalentTypeRule(aload_0, aload(0)).instructionHasEquivalentTypeRule(aload_1, aload(1)).instructionHasEquivalentTypeRule(aload_2, aload(2)).instructionHasEquivalentTypeRule(aload_3, aload(3)).
anewarray

Ananewarray instruction with operandCP is type safe iffCP refers to a constant pool entry denoting a class, interface, or array type, and one can legally replace a type matchingint on the incoming operand stack with an array with component typeCP yielding the outgoing type state.

instructionIsTypeSafe(anewarray(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    (CP = class(_, _) ; CP = arrayOf(_)),    validTypeTransition(Environment, [int], arrayOf(CP),                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
areturn

Anareturn instruction is type safe iff the enclosing method has a declared return type,ReturnType, that is areference type, and one can validly pop a type matchingReturnType off the incoming operand stack.

instructionIsTypeSafe(areturn, Environment, _Offset, StackFrame,                      afterGoto, ExceptionStackFrame) :-    thisMethodReturnType(Environment, ReturnType),    isAssignable(ReturnType, reference),    canPop(StackFrame, [ReturnType], _PoppedStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
arraylength

Anarraylength instruction is type safe iff one can validly replace an array type on the incoming operand stack with the typeint yielding the outgoing type state.

instructionIsTypeSafe(arraylength, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    nth1OperandStackIs(1, StackFrame, ArrayType),    arrayComponentType(ArrayType, _),    validTypeTransition(Environment, [top], int, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
astore,astore_<n>

Anastore instruction with operandIndex is type safe and yields an outgoing type stateNextStackFrame, if a store instruction with operandIndex and typereference is type safe and yields an outgoing type stateNextStackFrame.

instructionIsTypeSafe(astore(Index), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    storeIsTypeSafe(Environment, Index, reference, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The instructionsastore_<n>, for 0n 3, are type safe iff the equivalentastore instruction is type safe.

instructionHasEquivalentTypeRule(astore_0, astore(0)).instructionHasEquivalentTypeRule(astore_1, astore(1)).instructionHasEquivalentTypeRule(astore_2, astore(2)).instructionHasEquivalentTypeRule(astore_3, astore(3)).
athrow

Anathrow instruction is type safe iff the top of the operand stack matchesThrowable.

instructionIsTypeSafe(athrow, _Environment, _Offset, StackFrame,                      afterGoto, ExceptionStackFrame) :-    isBootstrapLoader(BL),    canPop(StackFrame, [class('java/lang/Throwable', BL)], _PoppedStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
baload

Abaload instruction is type safe iff one can validly replace types matchingint and a small array type on the incoming operand stack withint yielding the outgoing type state.

instructionIsTypeSafe(baload, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :    nth1OperandStackIs(2, StackFrame, ArrayType),    isSmallArray(ArrayType),    validTypeTransition(Environment, [int, top], int,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

An array type is asmall array type if it is an array ofbyte, an array ofboolean, or a subtype thereof (null).

isSmallArray(arrayOf(byte)).isSmallArray(arrayOf(boolean)).isSmallArray(null).
bastore

Abastore instruction is type safe iff one can validly pop types matchingint,int and a small array type off the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(bastore, _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    nth1OperandStackIs(3, StackFrame, ArrayType),    isSmallArray(ArrayType),    canPop(StackFrame, [int, int, top], NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
bipush

Abipush instruction is type safe iff the equivalentsipush instruction is type safe.

instructionHasEquivalentTypeRule(bipush(Value), sipush(Value)).
caload

Acaload instruction is type safe iff one can validly replace types matchingint and array ofchar on the incoming operand stack withint yielding the outgoing type state.

instructionIsTypeSafe(caload, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [int, arrayOf(char)], int,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
castore

Acastore instruction is type safe iff one can validly pop types matchingint,int and array ofchar off the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(castore, _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    canPop(StackFrame, [int, int, arrayOf(char)], NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
checkcast

Acheckcast instruction with operandCP is type safe iffCP refers to a constant pool entry denoting either a class or an array, and one can validly replace the typeObject on top of the incoming operand stack with the type denoted byCP yielding the outgoing type state.

instructionIsTypeSafe(checkcast(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    (CP = class(_, _) ; CP = arrayOf(_)),    isBootstrapLoader(BL),    validTypeTransition(Environment, [class('java/lang/Object', BL)], CP,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
d2f,d2i,d2l

Ad2f instruction is type safe if one can validly popdouble off the incoming operand stack and replace it withfloat, yielding the outgoing type state.

instructionIsTypeSafe(d2f, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [double], float,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Ad2i instruction is type safe if one can validly popdouble off the incoming operand stack and replace it withint, yielding the outgoing type state.

instructionIsTypeSafe(d2i, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [double], int,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Ad2l instruction is type safe if one can validly popdouble off the incoming operand stack and replace it withlong, yielding the outgoing type state.

instructionIsTypeSafe(d2l, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [double], long,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
dadd

Adadd instruction is type safe iff one can validly replace types matchingdouble anddouble on the incoming operand stack withdouble yielding the outgoing type state.

instructionIsTypeSafe(dadd, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [double, double], double,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
daload

Adaload instruction is type safe iff one can validly replace types matchingint and array ofdouble on the incoming operand stack withdouble yielding the outgoing type state.

instructionIsTypeSafe(daload, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [int, arrayOf(double)], double,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
dastore

Adastore instruction is type safe iff one can validly pop types matchingdouble,int and array ofdouble off the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(dastore, _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    canPop(StackFrame, [double, int, arrayOf(double)], NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
dcmp<op>

Adcmpg instruction is type safe iff one can validly replace types matchingdouble anddouble on the incoming operand stack withint yielding the outgoing type state.

instructionIsTypeSafe(dcmpg, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [double, double], int,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Adcmpl instruction is type safe iff the equivalentdcmpg instruction is type safe.

instructionHasEquivalentTypeRule(dcmpl, dcmpg).
dconst_<d>

Adconst_0 instruction is type safe if one can validly push the typedouble onto the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(dconst_0, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [], double, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Adconst_1 instruction is type safe iff the equivalentdconst_0 instruction is type safe.

instructionHasEquivalentTypeRule(dconst_1, dconst_0).
ddiv

Addiv instruction is type safe iff the equivalentdadd instruction is type safe.

instructionHasEquivalentTypeRule(ddiv, dadd).
dload,dload_<n>

Adload instruction with operandIndex is type safe and yields an outgoing type stateNextStackFrame, if a load instruction with operandIndex and typedouble is type safe and yields an outgoing type stateNextStackFrame.

instructionIsTypeSafe(dload(Index), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    loadIsTypeSafe(Environment, Index, double, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The instructionsdload_<n>, for 0n 3, are typesafe iff the equivalentdload instruction is type safe.

instructionHasEquivalentTypeRule(dload_0, dload(0)).instructionHasEquivalentTypeRule(dload_1, dload(1)).instructionHasEquivalentTypeRule(dload_2, dload(2)).instructionHasEquivalentTypeRule(dload_3, dload(3)).
dmul

Admul instruction is type safe iff the equivalentdadd instruction is type safe.

instructionHasEquivalentTypeRule(dmul, dadd).
dneg

Adneg instruction is type safe iff there is a type matchingdouble on the incoming operand stack. Thedneg instruction does not alter the type state.

instructionIsTypeSafe(dneg, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [double], double,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
drem

Adrem instruction is type safe iff the equivalentdadd instruction is type safe.

instructionHasEquivalentTypeRule(drem, dadd).
dreturn

Adreturn instruction is type safe if the enclosing method has a declared return type ofdouble, and one can validly pop a type matchingdouble off the incoming operand stack.

instructionIsTypeSafe(dreturn, Environment, _Offset, StackFrame,                      afterGoto, ExceptionStackFrame) :-    thisMethodReturnType(Environment, double),    canPop(StackFrame, [double], _PoppedStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
dstore,dstore_<n>

Adstore instruction with operandIndex is type safe and yields an outgoing type stateNextStackFrame, if a store instruction with operandIndex and typedouble is type safe and yields an outgoing type stateNextStackFrame.

instructionIsTypeSafe(dstore(Index), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    storeIsTypeSafe(Environment, Index, double, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The instructionsdstore_<n>, for 0n 3, are type safe iff the equivalentdstore instruction is type safe.

instructionHasEquivalentTypeRule(dstore_0, dstore(0)).instructionHasEquivalentTypeRule(dstore_1, dstore(1)).instructionHasEquivalentTypeRule(dstore_2, dstore(2)).instructionHasEquivalentTypeRule(dstore_3, dstore(3)).
dsub

Adsub instruction is type safe iff the equivalentdadd instruction is type safe.

instructionHasEquivalentTypeRule(dsub, dadd).
dup

Adup instruction is type safe iff one can validly replace a category 1 type,Type, with the typesType,Type, yielding the outgoing type state.

instructionIsTypeSafe(dup, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    StackFrame = frame(Locals, InputOperandStack, Flags),    popCategory1(InputOperandStack, Type, _),    canSafelyPush(Environment, InputOperandStack, Type, OutputOperandStack),    NextStackFrame = frame(Locals, OutputOperandStack, Flags),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
dup_x1

Adup_x1 instruction is type safe iff one can validly replace two category 1 types,Type1, andType2, on the incoming operand stack with the typesType1,Type2,Type1, yielding the outgoing type state.

instructionIsTypeSafe(dup_x1, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    StackFrame = frame(Locals, InputOperandStack, Flags),    popCategory1(InputOperandStack, Type1, Stack1),    popCategory1(Stack1, Type2, Rest),    canSafelyPushList(Environment, Rest, [Type1, Type2, Type1],                      OutputOperandStack),    NextStackFrame = frame(Locals, OutputOperandStack, Flags),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
dup_x2

Adup_x2 instruction is type safe iff it is atype safe form of thedup_x2 instruction.

instructionIsTypeSafe(dup_x2, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    StackFrame = frame(Locals, InputOperandStack, Flags),    dup_x2FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack),    NextStackFrame = frame(Locals, OutputOperandStack, Flags),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Adup_x2 instruction is atype safe form of thedup_x2 instruction iff it is atype safe form 1dup_x2 instruction or atype safe form 2dup_x2 instruction.

dup_x2FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    dup_x2Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).dup_x2FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    dup_x2Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).

Adup_x2 instruction is atype safe form 1dup_x2 instruction iff one can validly replace three category 1 types,Type1,Type2,Type3 on the incoming operand stack with the typesType1,Type2,Type3,Type1, yielding the outgoing type state.

dup_x2Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    popCategory1(InputOperandStack, Type1, Stack1),    popCategory1(Stack1, Type2, Stack2),    popCategory1(Stack2, Type3, Rest),    canSafelyPushList(Environment, Rest, [Type1, Type3, Type2, Type1],                      OutputOperandStack).

Adup_x2 instruction is atype safe form 2dup_x2 instruction iff one can validly replace a category 1 type,Type1, and a category 2 type,Type2, on the incoming operand stack with the typesType1,Type2,Type1, yielding the outgoing type state.

dup_x2Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    popCategory1(InputOperandStack, Type1, Stack1),    popCategory2(Stack1, Type2, Rest),    canSafelyPushList(Environment, Rest, [Type1, Type2, Type1],                      OutputOperandStack).
dup2

Adup2 instruction is type safe iff it is atype safe form of thedup2 instruction.

instructionIsTypeSafe(dup2, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    StackFrame = frame(Locals, InputOperandStack, Flags),    dup2FormIsTypeSafe(Environment,InputOperandStack, OutputOperandStack),    NextStackFrame = frame(Locals, OutputOperandStack, Flags),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Adup2 instruction is atype safe form of thedup2 instruction iff it is atype safe form 1dup2 instruction or atype safe form 2dup2 instruction.

dup2FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    dup2Form1IsTypeSafe(Environment,InputOperandStack, OutputOperandStack).dup2FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    dup2Form2IsTypeSafe(Environment,InputOperandStack, OutputOperandStack).

Adup2 instruction is atype safe form 1dup2 instruction iff one can validly replace two category 1 types,Type1 andType2 on the incoming operand stack with the typesType1,Type2,Type1,Type2, yielding the outgoing type state.

dup2Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack):-    popCategory1(InputOperandStack, Type1, TempStack),    popCategory1(TempStack, Type2, _),    canSafelyPushList(Environment, InputOperandStack, [Type2, Type1],                      OutputOperandStack).

Adup2 instruction is atype safe form 2dup2 instruction iff one can validly replace a category 2 type,Type on the incoming operand stack with the typesType,Type, yielding the outgoing type state.

dup2Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack):-    popCategory2(InputOperandStack, Type, _),    canSafelyPush(Environment, InputOperandStack, Type, OutputOperandStack).
dup2_x1

Adup2_x1 instruction is type safe iff it is atype safe form of thedup2_x1 instruction.

instructionIsTypeSafe(dup2_x1, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    StackFrame = frame(Locals, InputOperandStack, Flags),    dup2_x1FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack),    NextStackFrame = frame(Locals, OutputOperandStack, Flags),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Adup2_x1 instruction is atype safe form of thedup2_x1 instruction iff it is atype safe form 1dup2_x1 instruction or atype safe form 2dup_x2 instruction.

dup2_x1FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    dup2_x1Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).dup2_x1FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    dup2_x1Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).

Adup2_x1 instruction is atype safe form 1dup2_x1 instruction iff one can validly replace three category 1 types,Type1,Type2,Type3, on the incoming operand stack with the typesType1,Type2,Type3,Type1,Type2, yielding the outgoing type state.

dup2_x1Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    popCategory1(InputOperandStack, Type1, Stack1),    popCategory1(Stack1, Type2, Stack2),    popCategory1(Stack2, Type3, Rest),    canSafelyPushList(Environment, Rest, [Type2, Type1, Type3, Type2, Type1],                      OutputOperandStack).

Adup2_x1 instruction is atype safe form 2dup2_x1 instruction iff one can validly replace a category 2 type,Type1, and a category 1 type,Type2, on the incoming operand stack with the typesType1,Type2,Type1, yielding the outgoing type state.

dup2_x1Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    popCategory2(InputOperandStack, Type1, Stack1),    popCategory1(Stack1, Type2, Rest),    canSafelyPushList(Environment, Rest, [Type1, Type2, Type1],                      OutputOperandStack).
dup2_x2

Adup2_x2 instruction is type safe iff it is atype safe form of thedup2_x2 instruction.

instructionIsTypeSafe(dup2_x2, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    StackFrame = frame(Locals, InputOperandStack, Flags),    dup2_x2FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack),    NextStackFrame = frame(Locals, OutputOperandStack, Flags),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Adup2_x2 instruction is atype safe form of thedup2_x2 instruction iff one of the following holds:

  • it is atype safe form 1dup2_x2 instruction.

  • it is atype safe form 2dup2_x2 instruction.

  • it is atype safe form 3dup2_x2 instruction.

  • it is atype safe form 4dup2_x2 instruction.

dup2_x2FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    dup2_x2Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).dup2_x2FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    dup2_x2Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).dup2_x2FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    dup2_x2Form3IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).dup2_x2FormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    dup2_x2Form4IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).

Adup2_x2 instruction is atype safe form 1dup2_x2 instruction iff one can validly replace four category 1 types,Type1,Type2,Type3,Type4, on the incoming operand stack with the typesType1,Type2,Type3,Type4,Type1,Type2, yielding the outgoing type state.

dup2_x2Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    popCategory1(InputOperandStack, Type1, Stack1),    popCategory1(Stack1, Type2, Stack2),    popCategory1(Stack2, Type3, Stack3),    popCategory1(Stack3, Type4, Rest),    canSafelyPushList(Environment, Rest,                      [Type2, Type1, Type4, Type3, Type2, Type1],                      OutputOperandStack).

Adup2_x2 instruction is atype safe form 2dup2_x2 instruction iff one can validly replace a category 2 type,Type1, and two category 1 types,Type2,Type3, on the incoming operand stack with the typesType1,Type2,Type3,Type1, yielding the outgoing type state.

dup2_x2Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    popCategory2(InputOperandStack, Type1, Stack1),    popCategory1(Stack1, Type2, Stack2),    popCategory1(Stack2, Type3, Rest),    canSafelyPushList(Environment, Rest,                      [Type1, Type3, Type2, Type1],                      OutputOperandStack).

Adup2_x2 instruction is atype safe form 3dup2_x2 instruction iff one can validly replace two category 1 types,Type1,Type2, and a category 2 type,Type3, on the incoming operand stack with the typesType1,Type2,Type3,Type1,Type2, yielding the outgoing type state.

dup2_x2Form3IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    popCategory1(InputOperandStack, Type1, Stack1),    popCategory1(Stack1, Type2, Stack2),    popCategory2(Stack2, Type3, Rest),    canSafelyPushList(Environment, Rest,                      [Type2, Type1, Type3, Type2, Type1],                      OutputOperandStack).

Adup2_x2 instruction is atype safe form 4dup2_x2 instruction iff one can validly replace two category 2 types,Type1,Type2, on the incoming operand stack with the typesType1,Type2,Type1, yielding the outgoing type state.

dup2_x2Form4IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-    popCategory2(InputOperandStack, Type1, Stack1),    popCategory2(Stack1, Type2, Rest),    canSafelyPushList(Environment, Rest, [Type1, Type2, Type1],                      OutputOperandStack).
f2d,f2i,f2l

Anf2d instruction is type safe if one can validly popfloat off the incoming operand stack and replace it withdouble, yielding the outgoing type state.

instructionIsTypeSafe(f2d, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [float], double,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Anf2i instruction is type safe if one can validly popfloat off the incoming operand stack and replace it withint, yielding the outgoing type state.

instructionIsTypeSafe(f2i, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [float], int,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Anf2l instruction is type safe if one can validly popfloat off the incoming operand stack and replace it withlong, yielding the outgoing type state.

instructionIsTypeSafe(f2l, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [float], long,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
fadd

Anfadd instruction is type safe iff one can validly replace types matchingfloat andfloat on the incoming operand stack withfloat yielding the outgoing type state.

instructionIsTypeSafe(fadd, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [float, float], float,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
faload

Anfaload instruction is type safe iff one can validly replace types matchingint and array offloat on the incoming operand stack withfloat yielding the outgoing type state.

instructionIsTypeSafe(faload, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [int, arrayOf(float)], float,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
fastore

Anfastore instruction is type safe iff one can validly pop types matchingfloat,int and array offloat off the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(fastore, _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    canPop(StackFrame, [float, int, arrayOf(float)], NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
fcmp<op>

Anfcmpg instruction is type safe iff one can validly replace types matchingfloat andfloat on the incoming operand stack withint yielding the outgoing type state.

instructionIsTypeSafe(fcmpg, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [float, float], int,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Anfcmpl instruction is type safe iff the equivalentfcmpg instruction is type safe.

instructionHasEquivalentTypeRule(fcmpl, fcmpg).
fconst_<f>

Anfconst_0 instruction is type safe if one can validly push the typefloat onto the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(fconst_0, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [], float, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The rules for the other variants offconst are equivalent.

instructionHasEquivalentTypeRule(fconst_1, fconst_0).instructionHasEquivalentTypeRule(fconst_2, fconst_0).
fdiv

Anfdiv instruction is type safe iff the equivalentfadd instruction is type safe.

instructionHasEquivalentTypeRule(fdiv, fadd).
fload,fload_<n>

Anfload instruction with operandIndex is type safe and yields an outgoing type stateNextStackFrame, if a load instruction with operandIndex and typefloat is type safe and yields an outgoing type stateNextStackFrame.

instructionIsTypeSafe(fload(Index), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    loadIsTypeSafe(Environment, Index, float, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The instructionsfload_<n>, for 0n 3, are typesafe iff the equivalentfload instruction is type safe.

instructionHasEquivalentTypeRule(fload_0, fload(0)).instructionHasEquivalentTypeRule(fload_1, fload(1)).instructionHasEquivalentTypeRule(fload_2, fload(2)).instructionHasEquivalentTypeRule(fload_3, fload(3)).
fmul

Anfmul instruction is type safe iff the equivalentfadd instruction is type safe.

instructionHasEquivalentTypeRule(fmul, fadd).
fneg

Anfneg instruction is type safe iff there is a type matchingfloat on the incoming operand stack. Thefneg instruction does not alter the type state.

instructionIsTypeSafe(fneg, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [float], float,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
frem

Anfrem instruction is type safe iff the equivalentfadd instruction is type safe.

instructionHasEquivalentTypeRule(frem, fadd).
freturn

Anfreturn instruction is type safe if the enclosing method has a declared return type offloat, and one can validly pop a type matchingfloat off the incoming operand stack.

instructionIsTypeSafe(freturn, Environment, _Offset, StackFrame,                      afterGoto, ExceptionStackFrame) :-    thisMethodReturnType(Environment, float),    canPop(StackFrame, [float], _PoppedStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
fstore,fstore_<n>

Anfstore instruction with operandIndex is type safe and yields an outgoing type stateNextStackFrame, if a store instruction with operandIndex and typefloat is type safe and yields an outgoing type stateNextStackFrame.

instructionIsTypeSafe(fstore(Index), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    storeIsTypeSafe(Environment, Index, float, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The instructionsfstore_<n>, for 0n 3, are typesafe iff the equivalentfstore instruction is type safe.

instructionHasEquivalentTypeRule(fstore_0, fstore(0)).instructionHasEquivalentTypeRule(fstore_1, fstore(1)).instructionHasEquivalentTypeRule(fstore_2, fstore(2)).instructionHasEquivalentTypeRule(fstore_3, fstore(3)).
fsub

Anfsub instruction is type safe iff the equivalentfadd instruction is type safe.

instructionHasEquivalentTypeRule(fsub, fadd).
getfield

Agetfield instruction with operandCP is type safe iffCP refers to a constant pool entry denoting a field whose declared type isFieldType that is a member of a classFieldClassName, and one can validly replace a type matchingFieldClassName with typeFieldType on the incoming operand stack yielding the outgoing type state.FieldClassName 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(FieldClassName, FieldName, FieldDescriptor),    parseFieldDescriptor(FieldDescriptor, FieldType),    passesProtectedCheck(Environment, FieldClassName, FieldName,                         FieldDescriptor, StackFrame),    currentClassLoader(Environment, CurrentLoader),    validTypeTransition(Environment,                        [class(FieldClassName, CurrentLoader)], FieldType,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
getstatic

Agetstatic instruction with operandCP is type safe iffCP refers to a constant pool entry denoting a field whose declared type isFieldType, and one can validly pushFieldType on the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(getstatic(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    CP = field(_FieldClassName, _FieldName, FieldDescriptor),    parseFieldDescriptor(FieldDescriptor, FieldType),    validTypeTransition(Environment, [], FieldType,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
goto,goto_w

Agoto instruction is type safe iff its target operand is a valid branch target.

instructionIsTypeSafe(goto(Target), Environment, _Offset, StackFrame,                      afterGoto, ExceptionStackFrame) :-    targetIsTypeSafe(Environment, StackFrame, Target),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Agoto_w instruction is type safe iff the equivalentgoto instruction is type safe.

instructionHasEquivalentTypeRule(goto_w(Target), goto(Target)).
i2b,i2c,i2d,i2f,i2l,i2s

Ani2b instruction is type safe iff the equivalentineg instruction is type safe.

instructionHasEquivalentTypeRule(i2b, ineg).

Ani2c instruction is type safe iff the equivalentineg instruction is type safe.

instructionHasEquivalentTypeRule(i2c, ineg).

Ani2d instruction is type safe if one can validly popint off the incoming operand stack and replace it withdouble, yielding the outgoing type state.

instructionIsTypeSafe(i2d, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [int], double,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Ani2f instruction is type safe if one can validly popint off the incoming operand stack and replace it withfloat, yielding the outgoing type state.

instructionIsTypeSafe(i2f, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [int], float,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Ani2l instruction is type safe if one can validly popint off the incoming operand stack and replace it withlong, yielding the outgoing type state.

instructionIsTypeSafe(i2l, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [int], long,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Ani2s instruction is type safe iff the equivalentineg instruction is type safe.

instructionHasEquivalentTypeRule(i2s, ineg).
iadd

Aniadd instruction is type safe iff one can validly replace types matchingint andint on the incoming operand stack withint yielding the outgoing type state.

instructionIsTypeSafe(iadd, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [int, int], int,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
iaload

Aniaload instruction is type safe iff one can validly replace types matchingint and array ofint on the incoming operand stack withint yielding the outgoing type state.

instructionIsTypeSafe(iaload, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [int, arrayOf(int)], int,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
iand

Aniand instruction is type safe iff the equivalentiadd instruction is type safe.

instructionHasEquivalentTypeRule(iand, iadd).
iastore

Aniastore instruction is type safe iff one can validly pop types matchingint,int and array ofint off the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(iastore, _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    canPop(StackFrame, [int, int, arrayOf(int)], NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
iconst_<i>

Aniconst_m1 instruction is type safe if one can validly push the typeint onto the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(iconst_m1, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [], int, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The rules for the other variants oficonst are equivalent.

instructionHasEquivalentTypeRule(iconst_0, iconst_m1).instructionHasEquivalentTypeRule(iconst_1, iconst_m1).instructionHasEquivalentTypeRule(iconst_2, iconst_m1).instructionHasEquivalentTypeRule(iconst_3, iconst_m1).instructionHasEquivalentTypeRule(iconst_4, iconst_m1).instructionHasEquivalentTypeRule(iconst_5, iconst_m1).
idiv

Anidiv instruction is type safe iff the equivalentiadd instruction is type safe.

instructionHasEquivalentTypeRule(idiv, iadd).
if_acmp<cond>

Anif_acmpeq instruction is type safe iff one can validly pop types matchingreference andreference on the incoming operand stack yielding the outgoing type stateNextStackFrame, and the operand of the instruction,Target, is a valid branch target assuming an incoming type state ofNextStackFrame.

instructionIsTypeSafe(if_acmpeq(Target), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    canPop(StackFrame, [reference, reference], NextStackFrame),    targetIsTypeSafe(Environment, NextStackFrame, Target),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The rule forif_acmpne is identical.

instructionHasEquivalentTypeRule(if_acmpne(Target), if_acmpeq(Target)).
if_icmp<cond>

Anif_icmpeq instruction is type safe iff one can validly pop types matchingint andint on the incoming operand stack yielding the outgoing type stateNextStackFrame, and the operand of the instruction,Target, is a valid branch target assuming an incoming type state ofNextStackFrame.

instructionIsTypeSafe(if_icmpeq(Target), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    canPop(StackFrame, [int, int], NextStackFrame),    targetIsTypeSafe(Environment, NextStackFrame, Target),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The rules for all other variants of theif_icmp<cond> instruction are identical.

instructionHasEquivalentTypeRule(if_icmpge(Target), if_icmpeq(Target)).instructionHasEquivalentTypeRule(if_icmpgt(Target), if_icmpeq(Target)).instructionHasEquivalentTypeRule(if_icmple(Target), if_icmpeq(Target)).instructionHasEquivalentTypeRule(if_icmplt(Target), if_icmpeq(Target)).instructionHasEquivalentTypeRule(if_icmpne(Target), if_icmpeq(Target)).
if<cond>

Anifeq instruction is type safe iff one can validly pop a type matchingint off the incoming operand stack yielding the outgoing type stateNextStackFrame, and the operand of the instruction,Target, is a valid branch target assuming an incoming type state ofNextStackFrame.

instructionIsTypeSafe(ifeq(Target), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    canPop(StackFrame, [int], NextStackFrame),    targetIsTypeSafe(Environment, NextStackFrame, Target),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The rules for all other variations of theif<cond> instruction are identical.

instructionHasEquivalentTypeRule(ifge(Target), ifeq(Target)).instructionHasEquivalentTypeRule(ifgt(Target), ifeq(Target)).instructionHasEquivalentTypeRule(ifle(Target), ifeq(Target)).instructionHasEquivalentTypeRule(iflt(Target), ifeq(Target)).instructionHasEquivalentTypeRule(ifne(Target), ifeq(Target)).
ifnonnull,ifnull

Anifnonnull instruction is type safe iff one can validly pop a type matchingreference off the incoming operand stack yielding the outgoing type stateNextStackFrame, and the operand of the instruction,Target, is a valid branch target assuming an incoming type state ofNextStackFrame.

instructionIsTypeSafe(ifnonnull(Target), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    canPop(StackFrame, [reference], NextStackFrame),    targetIsTypeSafe(Environment, NextStackFrame, Target),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Anifnull instruction is type safe iff the equivalentifnonnull instruction is type safe.

instructionHasEquivalentTypeRule(ifnull(Target), ifnonnull(Target)).
iinc

Aniinc instruction with first operandIndex is type safe iffLIndex has typeint. Theiinc instruction does not change the type state.

instructionIsTypeSafe(iinc(Index, _Value), _Environment, _Offset,                      StackFrame, StackFrame, ExceptionStackFrame) :-    StackFrame = frame(Locals, _OperandStack, _Flags),    nth0(Index, Locals, int),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
iload,iload_<n>

Aniload instruction with operandIndex is type safe and yields an outgoing type stateNextStackFrame, if a load instruction with operandIndex and typeint is type safe and yields an outgoing type stateNextStackFrame.

instructionIsTypeSafe(iload(Index), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    loadIsTypeSafe(Environment, Index, int, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The instructionsiload_<n>, for 0n 3, are typesafe iff the equivalentiload instruction is type safe.

instructionHasEquivalentTypeRule(iload_0, iload(0)).instructionHasEquivalentTypeRule(iload_1, iload(1)).instructionHasEquivalentTypeRule(iload_2, iload(2)).instructionHasEquivalentTypeRule(iload_3, iload(3)).
imul

Animul instruction is type safe iff the equivalentiadd instruction is type safe.

instructionHasEquivalentTypeRule(imul, iadd).
ineg

Anineg instruction is type safe iff there is a type matchingint on the incoming operand stack. Theineg instruction does not alter the type state.

instructionIsTypeSafe(ineg, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [int], int, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
instanceof

Aninstanceof instruction with operandCP is type safe iffCP refers to a constant pool entry denoting either a class or an array, and one can validly replace the typeObject on top of the incoming operand stack with typeint yielding the outgoing type state.

instructionIsTypeSafe(instanceof(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    (CP = class(_, _) ; CP = arrayOf(_)),    isBootstrapLoader(BL),    validTypeTransition(Environment, [class('java/lang/Object', BL)], int,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
invokedynamic

Aninvokedynamic instruction is type safe iff all of the following are true:

  • Its first operand,CP, refers to a constant pool entry denoting an dynamic call site with nameCallSiteName with descriptorDescriptor.

  • CallSiteName is not<init>.

  • CallSiteName is not<clinit>.

  • One can validly replace types matching the argument types given inDescriptor on the incoming operand stack with the return type given inDescriptor, yielding the outgoing type state.

instructionIsTypeSafe(invokedynamic(CP,0,0), Environment, _Offset,                      StackFrame, NextStackFrame, ExceptionStackFrame) :-    CP = dmethod(CallSiteName, Descriptor),    CallSiteName \= '<init>',    CallSiteName \= '<clinit>',    parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),    reverse(OperandArgList, StackArgList),    validTypeTransition(Environment, StackArgList, ReturnType,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
invokeinterface

Aninvokeinterface instruction is type safe iff all of the following are true:

  • Its first operand,CP, refers to a constant pool entry denoting an interface method namedMethodName with descriptorDescriptor that is a member of an interfaceMethodIntfName.

  • MethodName is not<init>.

  • MethodName is not<clinit>.

  • Its second operand,Count, is a valid count operand (see below).

  • One can validly replace types matching the typeMethodIntfName and the argument types given inDescriptor on the incoming operand stack with the return type given inDescriptor, yielding the outgoing type state.

instructionIsTypeSafe(invokeinterface(CP, Count, 0), Environment, _Offset,                      StackFrame, NextStackFrame, ExceptionStackFrame) :-    CP = imethod(MethodIntfName, MethodName, Descriptor),    MethodName \= '<init>',    MethodName \= '<clinit>',    parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),    currentClassLoader(Environment, CurrentLoader),    reverse([class(MethodIntfName, CurrentLoader) | OperandArgList],            StackArgList),    canPop(StackFrame, StackArgList, TempFrame),    validTypeTransition(Environment, [], ReturnType,                        TempFrame, NextStackFrame),    countIsValid(Count, StackFrame, TempFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

TheCount operand of aninvokeinterface instruction is valid if it equals the size of the arguments to the instruction. This is equal to the difference between the size ofInputFrame andOutputFrame.

countIsValid(Count, InputFrame, OutputFrame) :-    InputFrame = frame(_Locals1, OperandStack1, _Flags1),    OutputFrame = frame(_Locals2, OperandStack2, _Flags2),    length(OperandStack1, Length1),    length(OperandStack2, Length2),    Count =:= Length1 - Length2.
invokespecial

Aninvokespecial instruction is type safe iff all of the following are true:

  • Its first operand,CP, refers to a constant pool entry denoting a method namedMethodName with descriptorDescriptor that is a member of a classMethodClassName.

  • Either:

    • MethodName is not<init>.

    • MethodName is not<clinit>.

    • One can validly replace types matching the current class and the argument types given inDescriptor on the incoming operand stack with the return type given inDescriptor, yielding the outgoing type state.

    • One can validly replace types matching the classMethodClassName and the argument types given inDescriptor on the incoming operand stack with the return type given inDescriptor.

instructionIsTypeSafe(invokespecial(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    CP = method(MethodClassName, MethodName, Descriptor),    MethodName \= '<init>',    MethodName \= '<clinit>',    parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),    thisClass(Environment, class(CurrentClassName, CurrentLoader)),    isAssignable(class(CurrentClassName, CurrentLoader),                 class(MethodClassName,  CurrentLoader)),    reverse([class(CurrentClassName, CurrentLoader) | OperandArgList],            StackArgList),    validTypeTransition(Environment, StackArgList, ReturnType,                        StackFrame, NextStackFrame),    reverse([class(MethodClassName, CurrentLoader) | OperandArgList],            StackArgList2),    validTypeTransition(Environment, StackArgList2, ReturnType,                        StackFrame, _ResultStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

TheisAssignable clause enforces the structural constraint thatinvokespecial, for other than an instance initialization method, must name a method in the current class/interface or a superclass/superinterface.

The firstvalidTypeTransition clause enforces the structural constraint thatinvokespecial, for other than an instance initialization method, targets a receiver object of the current class or deeper. To see why, consider thatStackArgList simulates the list of types on the operand stack expected by the method, starting with the current class (the class performinginvokespecial). The actual types on the operand stack are inStackFrame. The effect ofvalidTypeTransition is to pop the first type from the operand stack inStackFrame and check it is a subtype of the first term ofStackArgList, namely the current class. Thus, the actual receiver type is compatible with the current class.

A sharp-eyed reader might notice that enforcing this structural constraint supercedes the structural constraint pertaining toinvokespecial of aprotected method. Thus, the Prolog code above makes no reference topassesProtectedCheck (§4.10.1.8), whereas the Prolog code forinvokespecial of an instance initialization method usespassesProtectedCheck to ensure the actual receiver type is compatible with the current class when certainprotected instance initialization methods are named.

The secondvalidTypeTransition clause enforces the structural constraint that any method invocation instruction must target a receiver object whose type is compatible with the type named by the instruction. To see why, consider thatStackArgList2 simulates the list of types on the operand stack expected by the method, starting with the type named by the instruction. Again, the actual types on the operand stack are inStackFrame, and the effect ofvalidTypeTransition is to check the actual receiver type inStackFrame is compatible with the type named by the instruction inStackArgList2.

  • Or:

    • MethodName is<init>.

    • Descriptor specifies avoid return type.

    • One can validly pop types matching the argument types given inDescriptor and an uninitialized type,UninitializedArg, off the incoming operand stack, yieldingOperandStack.

    • The outgoing type state is derived from the incoming type state by first replacing the incoming operand stack withOperandStack and then replacing all instances ofUninitializedArg with the type of instance being initialized.

    • If the instruction calls an instance initialization method on a class instance created by an earliernew instruction, and the method isprotected, the usage conforms to the special rules governing access toprotected members (§4.10.1.8).

instructionIsTypeSafe(invokespecial(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    CP = method(MethodClassName, '<init>', Descriptor),    parseMethodDescriptor(Descriptor, OperandArgList, void),    reverse(OperandArgList, StackArgList),    canPop(StackFrame, StackArgList, TempFrame),    TempFrame = frame(Locals, [uninitializedThis | OperandStack], Flags),    currentClassLoader(Environment, CurrentLoader),    rewrittenUninitializedType(uninitializedThis, Environment,                               class(MethodClassName, CurrentLoader), This),    rewrittenInitializationFlags(uninitializedThis, Flags, NextFlags),    substitute(uninitializedThis, This, OperandStack, NextOperandStack),    substitute(uninitializedThis, This, Locals, NextLocals),    substitute(uninitializedThis, top, Locals, ExceptionLocals),    NextStackFrame = frame(NextLocals, NextOperandStack, NextFlags),    ExceptionStackFrame = frame(ExceptionLocals, [], Flags).
instructionIsTypeSafe(invokespecial(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    CP = method(MethodClassName, '<init>', Descriptor),    parseMethodDescriptor(Descriptor, OperandArgList, void),    reverse(OperandArgList, StackArgList),    canPop(StackFrame, StackArgList, TempFrame),    TempFrame = frame(Locals, [uninitialized(Address) | OperandStack], Flags),    currentClassLoader(Environment, CurrentLoader),    rewrittenUninitializedType(uninitialized(Address), Environment,                               class(MethodClassName, CurrentLoader), This),    rewrittenInitializationFlags(uninitialized(Address), Flags, NextFlags),    substitute(uninitialized(Address), This, OperandStack, NextOperandStack),    substitute(uninitialized(Address), This, Locals, NextLocals),    substitute(uninitialized(Address), top, Locals, ExceptionLocals),    NextStackFrame = frame(NextLocals, NextOperandStack, NextFlags),    ExceptionStackFrame = frame(ExceptionLocals, [], Flags),    passesProtectedCheck(Environment, MethodClassName, '<init>',                         Descriptor, NextStackFrame).

To compute what type the uninitialized argument's type needs to be rewritten to, there are two cases:

  • If we are initializing an object within its constructor, its type is initiallyuninitializedThis. This type will be rewritten to the type of the class of the<init> method.

  • The second case arises from initialization of an object created bynew. The uninitialized arg type is rewritten toMethodClass, the type of the method holder of<init>. We check whether there really is anew instruction atAddress.

rewrittenUninitializedType(uninitializedThis, Environment,                           MethodClass, MethodClass) :-    MethodClass = class(MethodClassName, CurrentLoader),    thisClass(Environment, MethodClass).rewrittenUninitializedType(uninitializedThis, Environment,                           MethodClass, MethodClass) :-    MethodClass = class(MethodClassName, CurrentLoader),    thisClass(Environment, class(thisClassName, thisLoader)),    superclassChain(thisClassName, thisLoader, [MethodClass | Rest]).rewrittenUninitializedType(uninitialized(Address), Environment,                           MethodClass, MethodClass) :-    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 forinvokespecial of an<init> method is the sole motivation for passing back a distinct exception stack frame. The concern is that when initializing an object, theinvokespecial invocation could fail, leaving the object in a partially initialized, permanently unusable state. To prevent repeated initialization attempts after an object fails to initialize the first time, an exception handler must consider any references to the object stored in local variables to have typetop rather thanuninitializedThis oruninitialized(Offset).

In the special case of initializing the current object (that is, when invoking<init> for typeuninitializedThis), the original frame typically holds an uninitialized object in local variable 0 and has flagflagThisUninit. Normal termination ofinvokespecial initializes the uninitialized object and turns off theflagThisUninit flag. But if theinvokespecial invocation throws an exception, the exception frame contains the broken object (with typetop) and theflagThisUninit flag (the old flag). There is no way to perform a return instruction given that type state, so the handler would have to throw another exception (or loop forever). In fact, it's not even possible to express a handler with that type state, because there is no way for a stack frame, as expressed by theStackMapTable attribute (§4.7.4), to carryflagThisUninit without any accompanying use of typeuninitializedThis.

If not for these special constraints on object initialization, the local variable types and flags of the exception stack frame would always be the same as the local variable types and flags of the input stack frame.

invokestatic

Aninvokestatic instruction is type safe iff all of the following are true:

  • Its first operand,CP, refers to a constant pool entry denoting a method namedMethodName with descriptorDescriptor.

  • MethodName is not<init>.

  • MethodName is not<clinit>.

  • One can validly replace types matching the argument types given inDescriptor on the incoming operand stack with the return type given inDescriptor, yielding the outgoing type state.

instructionIsTypeSafe(invokestatic(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    CP = method(_MethodClassName, MethodName, Descriptor),    MethodName \= '<init>',    MethodName \= '<clinit>',    parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),    reverse(OperandArgList, StackArgList),    validTypeTransition(Environment, StackArgList, ReturnType,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
invokevirtual

Aninvokevirtual instruction is type safe iff all of the following are true:

  • Its first operand,CP, refers to a constant pool entry denoting a method namedMethodName with descriptorDescriptor that is a member of a classMethodClassName.

  • MethodName is not<init>.

  • MethodName is not<clinit>.

  • One can validly replace types matching the classMethodClassName and the argument types given inDescriptor on the incoming operand stack with the return type given inDescriptor, yielding the outgoing type state.

  • If the method isprotected, the usage conforms to the special rules governing access toprotected members (§4.10.1.8).

instructionIsTypeSafe(invokevirtual(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    CP = method(MethodClassName, MethodName, Descriptor),    MethodName \= '<init>',    MethodName \= '<clinit>',    parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),    reverse(OperandArgList, ArgList),    currentClassLoader(Environment, CurrentLoader),    reverse([class(MethodClassName, CurrentLoader) | OperandArgList],            StackArgList),    validTypeTransition(Environment, StackArgList, ReturnType,                        StackFrame, NextStackFrame),    canPop(StackFrame, ArgList, PoppedFrame),    passesProtectedCheck(Environment, MethodClassName, MethodName,                         Descriptor, PoppedFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
ior,irem

Anior instruction is type safe iff the equivalentiadd instruction is type safe.

instructionHasEquivalentTypeRule(ior, iadd).

Anirem instruction is type safe iff the equivalentiadd instruction is type safe.

instructionHasEquivalentTypeRule(irem, iadd).
ireturn

Anireturn instruction is type safe if the enclosing method has a declared return type ofint, and one can validly pop a type matchingint off the incoming operand stack.

instructionIsTypeSafe(ireturn, Environment, _Offset, StackFrame,                      afterGoto, ExceptionStackFrame) :-    thisMethodReturnType(Environment, int),    canPop(StackFrame, [int], _PoppedStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
ishl,ishr,iushr

Anishl instruction is type safe iff the equivalentiadd instruction is type safe.

instructionHasEquivalentTypeRule(ishl, iadd).

Anishr instruction is type safe iff the equivalentiadd instruction is type safe.

instructionHasEquivalentTypeRule(ishr, iadd).

Aniushr instruction is type safe iff the equivalentiadd instruction is type safe.

instructionHasEquivalentTypeRule(iushr, iadd).
istore,istore_<n>

Anistore instruction with operandIndex is type safe and yields an outgoing type stateNextStackFrame, if a store instruction with operandIndex and typeint is type safe and yields an outgoing type stateNextStackFrame.

instructionIsTypeSafe(istore(Index), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    storeIsTypeSafe(Environment, Index, int, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The instructionsistore_<n>, for 0n 3, are type safe iff the equivalentistore instruction is type safe.

instructionHasEquivalentTypeRule(istore_0, istore(0)).instructionHasEquivalentTypeRule(istore_1, istore(1)).instructionHasEquivalentTypeRule(istore_2, istore(2)).instructionHasEquivalentTypeRule(istore_3, istore(3)).
isub,ixor

Anisub instruction is type safe iff the equivalentiadd instruction is type safe.

instructionHasEquivalentTypeRule(isub, iadd).

Anixor instruction is type safe iff the equivalentiadd instruction is type safe.

instructionHasEquivalentTypeRule(ixor, iadd).
l2d,l2f,l2i

Anl2d instruction is type safe if one can validly poplong off the incoming operand stack and replace it withdouble, yielding the outgoing type state.

instructionIsTypeSafe(l2d, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [long], double,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Anl2f instruction is type safe if one can validly poplong off the incoming operand stack and replace it withfloat, yielding the outgoing type state.

instructionIsTypeSafe(l2f, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [long], float,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Anl2i instruction is type safe if one can validly poplong off the incoming operand stack and replace it withint, yielding the outgoing type state.

instructionIsTypeSafe(l2i, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [long], int,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
ladd

Anladd instruction is type safe iff one can validly replace types matchinglong andlong on the incoming operand stack withlong yielding the outgoing type state.

instructionIsTypeSafe(ladd, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [long, long], long,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
laload

Anlaload instruction is type safe iff one can validly replace types matchingint and array oflong on the incoming operand stack withlong yielding the outgoing type state.

instructionIsTypeSafe(laload, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [int, arrayOf(long)], long,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
land

Anland instruction is type safe iff the equivalentladd instruction is type safe.

instructionHasEquivalentTypeRule(land, ladd).
lastore

Anlastore instruction is type safe iff one can validly pop types matchinglong,int and array oflong off the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(lastore, _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    canPop(StackFrame, [long, int, arrayOf(long)], NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
lcmp

Alcmp instruction is type safe iff one can validly replace types matchinglong andlong on the incoming operand stack withint yielding the outgoing type state.

instructionIsTypeSafe(lcmp, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [long, long], int,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
lconst_<l>

Anlconst_0 instruction is type safe if one can validly push the typelong onto the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(lconst_0, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [], long, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Anlconst_1 instruction is type safe iff the equivalentlconst_0 instruction is type safe.

instructionHasEquivalentTypeRule(lconst_1, lconst_0).
ldc,ldc_w,ldc2_w

Anldc instruction with operandCP is type safe iffCP refers to a constant pool entry denoting an entity of typeType, whereType is loadable (§4.4), but notlong ordouble, and one can validly pushType onto the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(ldc(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    loadableConstant(CP, Type),    Type \= long,    Type \= double,    validTypeTransition(Environment, [], Type, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).loadableConstant(CP, Type) :-    member([CP, Type], [        [int(_),    int],        [float(_),  float],        [long(_),   long],        [double(_), double]    ]).loadableConstant(CP, Type) :-    isBootstrapLoader(BL),    member([CP, Type], [        [class(_),          class('java/lang/Class', BL)],        [string(_),         class('java/lang/String', BL)],        [methodHandle(_,_), class('java/lang/invoke/MethodHandle', BL)],        [methodType(_,_),   class('java/lang/invoke/MethodType', BL)]    ]).loadableConstant(CP, Type) :-    CP = dconstant(_, FieldDescriptor),    parseFieldDescriptor(FieldDescriptor, Type).

Anldc_w instruction is type safe iff the equivalentldc instruction is type safe.

instructionHasEquivalentTypeRule(ldc_w(CP), ldc(CP))

Anldc2_w instruction with operandCP is type safe iffCP refers to a constant pool entry denoting an entity of typeType, whereType is eitherlong ordouble, and one can validly pushType onto the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(ldc2_w(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    loadableConstant(CP, Type),    (Type = long ; Type = double),    validTypeTransition(Environment, [], Type, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
ldiv

Anldiv instruction is type safe iff the equivalentladd instruction is type safe.

instructionHasEquivalentTypeRule(ldiv, ladd).
lload,lload_<n>

Anlload instruction with operandIndex is type safe and yields an outgoing type stateNextStackFrame, if a load instruction with operandIndex and typelong is type safe and yields an outgoing type stateNextStackFrame.

instructionIsTypeSafe(lload(Index), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    loadIsTypeSafe(Environment, Index, long, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The instructionslload_<n>, for 0n 3, are type safe iff the equivalentlload instruction is type safe.

instructionHasEquivalentTypeRule(lload_0, lload(0)).instructionHasEquivalentTypeRule(lload_1, lload(1)).instructionHasEquivalentTypeRule(lload_2, lload(2)).instructionHasEquivalentTypeRule(lload_3, lload(3)).
lmul

Anlmul instruction is type safe iff the equivalentladd instruction is type safe.

instructionHasEquivalentTypeRule(lmul, ladd).
lneg

Anlneg instruction is type safe iff there is a type matchinglong on the incoming operand stack. Thelneg instruction does not alter the type state.

instructionIsTypeSafe(lneg, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [long], long,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
lookupswitch

Alookupswitch instruction is type safe if its keys are sorted, one can validly popint off the incoming operand stack yielding a new type stateBranchStackFrame, and all of the instruction's targets are valid branch targets assumingBranchStackFrame as their incoming type state.

instructionIsTypeSafe(lookupswitch(Targets, Keys), Environment, _, StackFrame,                      afterGoto, ExceptionStackFrame) :-    sort(Keys, Keys),    canPop(StackFrame, [int], BranchStackFrame),    checklist(targetIsTypeSafe(Environment, BranchStackFrame), Targets),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
lor,lrem

Alor instruction is type safe iff the equivalentladd instruction is type safe.

instructionHasEquivalentTypeRule(lor, ladd).

Anlrem instruction is type safe iff the equivalentladd instruction is type safe.

instructionHasEquivalentTypeRule(lrem, ladd).
lreturn

Anlreturn instruction is type safe if the enclosing method has a declared return type oflong, and one can validly pop a type matchinglong off the incoming operand stack.

instructionIsTypeSafe(lreturn, Environment, _Offset, StackFrame,                      afterGoto, ExceptionStackFrame) :-    thisMethodReturnType(Environment, long),    canPop(StackFrame, [long], _PoppedStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
lshl,lshr,lushr

Anlshl instruction is type safe if one can validly replace the typesint andlong on the incoming operand stack with the typelong yielding the outgoing type state.

instructionIsTypeSafe(lshl, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [int, long], long,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Anlshr instruction is type safe iff the equivalentlshl instruction is type safe.

instructionHasEquivalentTypeRule(lshr, lshl).

Anlushr instruction is type safe iff the equivalentlshl instruction is type safe.

instructionHasEquivalentTypeRule(lushr, lshl).
lstore,lstore_<n>

Anlstore instruction with operandIndex is type safe and yields an outgoing type stateNextStackFrame, if a store instruction with operandIndex and typelong is type safe and yields an outgoing type stateNextStackFrame.

instructionIsTypeSafe(lstore(Index), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    storeIsTypeSafe(Environment, Index, long, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The instructionslstore_<n>, for 0n 3, are type safe iff the equivalentlstore instruction is type safe.

instructionHasEquivalentTypeRule(lstore_0, lstore(0)).instructionHasEquivalentTypeRule(lstore_1, lstore(1)).instructionHasEquivalentTypeRule(lstore_2, lstore(2)).instructionHasEquivalentTypeRule(lstore_3, lstore(3)).
lsub,lxor

Anlsub instruction is type safe iff the equivalentladd instruction is type safe.

instructionHasEquivalentTypeRule(lsub, ladd).

Anlxor instruction is type safe iff the equivalentladd instruction is type safe.

instructionHasEquivalentTypeRule(lxor, ladd).
monitorenter,monitorexit

Amonitorenter instruction is type safe iff one can validly pop a type matchingreference off the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(monitorenter, _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    canPop(StackFrame, [reference], NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Amonitorexit instruction is type safe iff the equivalentmonitorenter instruction is type safe.

instructionHasEquivalentTypeRule(monitorexit, monitorenter).
multianewarray

Amultianewarray instruction with operandsCP andDim is type safe iffCP refers to a constant pool entry denoting an array type whose dimension is greater or equal toDim,Dim is strictly positive, and one can validly replaceDimint types on the incoming operand stack with the type denoted byCP yielding the outgoing type state.

instructionIsTypeSafe(multianewarray(CP, Dim), Environment, _Offset,                      StackFrame, NextStackFrame, ExceptionStackFrame) :-    CP = arrayOf(_),    classDimension(CP, Dimension),    Dimension >= Dim,    Dim > 0,    /* Make a list of Dim ints */    findall(int, between(1, Dim, _), IntList),    validTypeTransition(Environment, IntList, CP,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The dimension of an array type whose component type is also an array type is one more than the dimension of its component type.

classDimension(arrayOf(X), Dimension) :-    classDimension(X, Dimension1),    Dimension is Dimension1 + 1.classDimension(_, Dimension) :-    Dimension = 0.
new

Anew instruction with operandCP at offsetOffset is type safe iffCP refers to a constant pool entry denoting a class or interface type, the typeuninitialized(Offset) does not appear in the incoming operand stack, and one can validly pushuninitialized(Offset) onto the incoming operand stack and replaceuninitialized(Offset) withtop 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).

Thesubstitute predicate is defined in the rule forinvokespecial (§invokespecial).

newarray

Anewarray instruction with operandTypeCode is type safe iffTypeCode corresponds to the primitive typeElementType, and one can validly replace the typeint on the incoming operand stack with the type 'array ofElementType', yielding the outgoing type state.

instructionIsTypeSafe(newarray(TypeCode), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    primitiveArrayInfo(TypeCode, _TypeChar, ElementType, _VerifierType),    validTypeTransition(Environment, [int], arrayOf(ElementType),                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

The correspondence between type codes and primitive types is specified by the following predicate:

primitiveArrayInfo(4,  0'Z, boolean, int).primitiveArrayInfo(5,  0'C, char,    int).primitiveArrayInfo(6,  0'F, float,   float).primitiveArrayInfo(7,  0'D, double,  double).primitiveArrayInfo(8,  0'B, byte,    int).primitiveArrayInfo(9,  0'S, short,   int).primitiveArrayInfo(10, 0'I, int,     int).primitiveArrayInfo(11, 0'J, long,    long).
nop

Anop instruction is always type safe. Thenop instruction does not affect the type state.

instructionIsTypeSafe(nop, _Environment, _Offset, StackFrame,                      StackFrame, ExceptionStackFrame) :-    exceptionStackFrame(StackFrame, ExceptionStackFrame).
pop,pop2

Apop instruction is type safe iff one can validly pop a category 1 type off the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(pop, _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    StackFrame = frame(Locals, [Type | Rest], Flags),    popCategory1([Type | Rest], Type, Rest),    NextStackFrame = frame(Locals, Rest, Flags),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Apop2 instruction is type safe iff it is atype safe form of thepop2 instruction.

instructionIsTypeSafe(pop2, _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    StackFrame = frame(Locals, InputOperandStack, Flags),    pop2SomeFormIsTypeSafe(InputOperandStack, OutputOperandStack),    NextStackFrame = frame(Locals, OutputOperandStack, Flags),    exceptionStackFrame(StackFrame, ExceptionStackFrame).

Apop2 instruction is atype safe form of thepop2 instruction iff it is atype safe form 1pop2 instruction or atype safe form 2pop2 instruction.

pop2SomeFormIsTypeSafe(InputOperandStack, OutputOperandStack) :-    pop2Form1IsTypeSafe(InputOperandStack, OutputOperandStack).pop2SomeFormIsTypeSafe(InputOperandStack, OutputOperandStack) :-    pop2Form2IsTypeSafe(InputOperandStack, OutputOperandStack).

Apop2 instruction is atype safe form 1pop2 instruction iff one can validly pop two types of size 1 off the incoming operand stack yielding the outgoing type state.

pop2Form1IsTypeSafe([Type1, Type2 | Rest], Rest) :-    popCategory1([Type1 | Rest], Type1, Rest),    popCategory1([Type2 | Rest], Type2, Rest).

Apop2 instruction is atype safe form 2pop2 instruction iff one can validly pop a type of size 2 off the incoming operand stack yielding the outgoing type state.

pop2Form2IsTypeSafe([top, Type | Rest], Rest) :-    popCategory2([top, Type | Rest], Type, Rest).
putfield

Aputfield instruction with operandCP is type safe iff all of the following are true:

  • Its first operand,CP, refers to a constant pool entry denoting a field whose declared type isFieldType that is a member of a classFieldClassName.FieldClassName must not be an array type.

  • Either:

    • One can validly pop types matchingFieldType andFieldClassName off the incoming operand stack yielding the outgoing type state.

    • protected fields are subject to additional checks (§4.10.1.8).

instructionIsTypeSafe(putfield(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    CP = field(FieldClassName, FieldName, FieldDescriptor),    parseFieldDescriptor(FieldDescriptor, FieldType),    canPop(StackFrame, [FieldType], PoppedFrame),    passesProtectedCheck(Environment, FieldClassName, FieldName,                         FieldDescriptor, PoppedFrame),    currentClassLoader(Environment, CurrentLoader),    canPop(StackFrame, [FieldType, class(FieldClassName, CurrentLoader)],           NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
  • Or:

    • If the instruction occurs in an instance initialization method of the classFieldClassName and assigns to a field declared by the class, then one can validly pop types matchingFieldType anduninitializedThis off the incoming operand stack yielding the outgoing type state. This allows instance fields ofthis that are declared in the current class to be assigned prior to complete initialization ofthis.

instructionIsTypeSafe(putfield(CP), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    CP = field(FieldClassName, FieldName, FieldDescriptor),    parseFieldDescriptor(FieldDescriptor, FieldType),    Environment = environment(CurrentClass, CurrentMethod, _, _, _, _),    CurrentClass = class(FieldClassName, _),    isInit(CurrentMethod),    classDeclaresMember(CurrentClass, FieldName, FieldDescriptor),    canPop(StackFrame, [FieldType, uninitializedThis], NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
putstatic

Aputstatic instruction with operandCP is type safe iffCP refers to a constant pool entry denoting a field whose declared type isFieldType, and one can validly pop a type matchingFieldType off the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(putstatic(CP), _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    CP = field(_FieldClassName, _FieldName, FieldDescriptor),    parseFieldDescriptor(FieldDescriptor, FieldType),    canPop(StackFrame, [FieldType], NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
return

Areturn instruction is type safe if the enclosing method declares avoid return type, and either:

  • The enclosing method is not an<init> method, or

  • this has already been completely initialized at the point where the instruction occurs.

instructionIsTypeSafe(return, Environment, _Offset, StackFrame,                      afterGoto, ExceptionStackFrame) :-    thisMethodReturnType(Environment, void),    StackFrame = frame(_Locals, _OperandStack, Flags),    notMember(flagThisUninit, Flags),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
saload

Ansaload instruction is type safe iff one can validly replace types matchingint and array ofshort on the incoming operand stack withint yielding the outgoing type state.

instructionIsTypeSafe(saload, Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [int, arrayOf(short)], int,                        StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
sastore

Ansastore instruction is type safe iff one can validly pop types matchingint,int, and array ofshort off the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(sastore, _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    canPop(StackFrame, [int, int, arrayOf(short)], NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
sipush

Ansipush instruction is type safe iff one can validly push the typeint onto the incoming operand stack yielding the outgoing type state.

instructionIsTypeSafe(sipush(_Value), Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    validTypeTransition(Environment, [], int, StackFrame, NextStackFrame),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
swap

Aswap instruction is type safe iff one can validly replace two category 1 types,Type1 andType2, on the incoming operand stack with the typesType2 andType1 yielding the outgoing type state.

instructionIsTypeSafe(swap, _Environment, _Offset, StackFrame,                      NextStackFrame, ExceptionStackFrame) :-    StackFrame = frame(_Locals, [Type1, Type2 | Rest], _Flags),    popCategory1([Type1 | Rest], Type1, Rest),    popCategory1([Type2 | Rest], Type2, Rest),    NextStackFrame = frame(_Locals, [Type2, Type1 | Rest], _Flags),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
tableswitch

Atableswitch instruction is type safe if its keys are sorted, one can validly popint off the incoming operand stack yielding a new type stateBranchStackFrame, and all of the instruction's targets are valid branch targets assumingBranchStackFrame as their incoming type state.

instructionIsTypeSafe(tableswitch(Targets, Keys), Environment, _Offset,                      StackFrame, afterGoto, ExceptionStackFrame) :-    sort(Keys, Keys),    canPop(StackFrame, [int], BranchStackFrame),    checklist(targetIsTypeSafe(Environment, BranchStackFrame), Targets),    exceptionStackFrame(StackFrame, ExceptionStackFrame).
wide

Thewide instructions follow the same rules as the instructions they widen.

instructionHasEquivalentTypeRule(wide(WidenedInstruction),                                 WidenedInstruction).

4.10.2. Verification by Type Inference

Aclass file that does not contain aStackMapTable attribute (which necessarily has a version number of 49.0 or below) must be verified using type inference.

4.10.2.1. The Process of Verification by Type Inference

During linking, the verifier checks thecode array of theCode attribute for each method of theclass file by performing data-flow analysis on each method. The verifier ensures that at any given point in the program, no matter what code path is taken to reach that point, all of the following are true:

  • The operand stack is always the same size and contains the same types of values.

  • No local variable is accessed unless it is known to contain a value of an appropriate type.

  • Methods are invoked with the appropriate arguments.

  • Fields are assigned only using values of appropriate types.

  • All opcodes have appropriately typed arguments on the operand stack and in the local variable array.

For efficiency reasons, certain tests that could in principle be performed by the verifier are delayed until the first time the code for the method is actually invoked. In so doing, the verifier avoids loadingclass files unless it has to.

For example, if a method invokes another method that returns an instance of classA, and that instance is assigned only to a field of the same type, the verifier does not bother to check if the classA actually exists. However, if it is assigned to a field of the typeB, the definitions of bothA andB must be loaded in to ensure thatA is a subclass ofB.

4.10.2.2. The Bytecode Verifier

The code for each method is verified independently. First, the bytes that make up the code are broken up into a sequence of instructions, and the index into thecode array of the start of each instruction is placed in an array. The verifier then goes through the code a second time and parses the instructions. During this pass a data structure is built to hold information about each Java Virtual Machine instruction in the method. The operands, if any, of each instruction are checked to make sure they are valid. For instance:

  • Branches must be within the bounds of thecode array for the method.

  • The targets of all control-flow instructions are each the start of an instruction. In the case of awide instruction, thewide opcode is considered the start of the instruction, and the opcode giving the operation modified by thatwide instruction is not considered to start an instruction. Branches into the middle of an instruction are disallowed.

  • No instruction can access or modify a local variable at an index greater than or equal to the number of local variables that its method indicates it allocates.

  • All references to the constant pool must be to an entry of the appropriate type. (For example, the instructiongetfield must reference a field.)

  • The code does not end in the middle of an instruction.

  • Execution cannot fall off the end of the code.

  • For each exception handler, the starting and ending point of code protected by the handler must be at the beginning of an instruction or, in the case of the ending point, immediately past the end of the code. The starting point must be before the ending point. The exception handler code must start at a valid instruction, and it must not start at an opcode being modified by thewide instruction.

For each instruction of the method, the verifier records the contents of the operand stack and the contents of the local variable array prior to the execution of that instruction. For the operand stack, it needs to know the stack height and the type of each value on it. For each local variable, it needs to know either the type of the contents of that local variable or that the local variable contains an unusable or unknown value (it might be uninitialized). The bytecode verifier does not need to distinguish between the integral types (e.g.,byte,short,char) when determining the value types on the operand stack.

Next, a data-flow analyzer is initialized. For the first instruction of the method, the local variables that represent parameters initially contain values of the types indicated by the method's type descriptor; the operand stack is empty. All other local variables contain an illegal value. For the other instructions, which have not been examined yet, no information is available regarding the operand stack or local variables.

Finally, the data-flow analyzer is run. For each instruction, a "changed" bit indicates whether this instruction needs to be looked at. Initially, the "changed" bit is set only for the first instruction. The data-flow analyzer executes the following loop:

  1. Select a Java Virtual Machine instruction whose "changed" bit is set. If no instruction remains whose "changed" bit is set, the method has successfully been verified. Otherwise, turn off the "changed" bit of the selected instruction.

  2. Model the effect of the instruction on the operand stack and local variable array by doing the following:

    • If the instruction uses values from the operand stack, ensure that there are a sufficient number of values on the stack and that the top values on the stack are of an appropriate type. Otherwise, verification fails.

    • If the instruction uses a local variable, ensure that the specified local variable contains a value of the appropriate type. Otherwise, verification fails.

    • If the instruction pushes values onto the operand stack, ensure that there is sufficient room on the operand stack for the new values. Add the indicated types to the top of the modeled operand stack.

    • If the instruction modifies a local variable, record that the local variable now contains the new type.

  3. Determine the instructions that can follow the current instruction. Successor instructions can be one of the following:

    • The next instruction, if the current instruction is not an unconditional control transfer instruction (for instance,goto,return, orathrow). Verification fails if it is possible to "fall off" the last instruction of the method.

    • The target(s) of a conditional or unconditional branch or switch.

    • Any exception handlers for this instruction.

  4. Merge the state of the operand stack and local variable array at the end of the execution of the current instruction into each of the successor instructions, as follows:

    • If this is the first time the successor instruction has been visited, record that the operand stack and local variable values calculated in step 2 are the state of the operand stack and local variable array prior to executing the successor instruction. Set the "changed" bit for the successor instruction.

    • If the successor instruction has been seen before, merge the operand stack and local variable values calculated in step 2 into the values already there. Set the "changed" bit if there is any modification to the values.

    In the special case of control transfer to an exception handler:

    • Record that a single object, of the exception type indicated by the exception handler, is the state of the operand stack prior to executing the successor instruction. There must be sufficient room on the operand stack for this single value, as if an instruction had pushed it.

    • Record that the local variable values from immediately before step 2 are the state of the local variable array prior to executing the successor instruction. The local variable values calculated in step 2 are irrelevant.

  5. Continue at step 1.

To merge two operand stacks, the number of values on each stack must be identical. The types of values on the stacks must also be identical, except that differently typedreference values may appear at corresponding places on the two stacks. In this case, the merged operand stack contains a reference type representing the first common superclass, superinterface, or array supertype of the two types. Such areference type always exists because the typeObject is a superclass of all class, interface, and array types. If the operand stacks cannot be merged, verification of the method fails.

To merge two local variable array states, corresponding pairs of local variables are compared. The value of the merged local variable is computed using the rules above, except that the corresponding values are permitted to be different primitive types. In that case, the verifier records that the merged local variable contains an unusable value.

If the data-flow analyzer runs on a method without reporting a verification failure, then the method has been successfully verified by theclass file verifier.

Certain instructions and data types complicate the data-flow analyzer. We now examine each of these in more detail.

4.10.2.3. Values of Typeslong anddouble

Values of thelong anddouble types are treated specially by the verification process.

Whenever a value of typelong ordouble is moved into a local variable at indexn, indexn+1 is specially marked to indicate that it has been reserved by the value at indexn and must not be used as a local variable index. Any value previously at indexn+1 becomes unusable.

Whenever a value is moved to a local variable at indexn, the indexn-1 is examined to see if it is the index of a value of typelong ordouble. If so, the local variable at indexn-1 is changed to indicate that it now contains an unusable value. Since the local variable at indexn has been overwritten, the local variable at indexn-1 cannot represent a value of typelong ordouble.

Dealing with values of typeslong ordouble on the operand stack is simpler; the verifier treats them as single values on the stack. For example, the verification code for thedadd opcode (add twodouble values) checks that the top two items on the stack are both of typedouble. When calculating operand stack length, values of typelong anddouble have length two.

Untyped instructions that manipulate the operand stack must treat values of typelong anddouble as atomic (indivisible). For example, the verifier reports a failure if the top value on the stack is adouble and it encounters an instruction such aspop ordup. The instructionspop2 ordup2 must be used instead.

4.10.2.4. Instance Initialization Methods and Newly Created Objects

Creating a new class instance is a multistep process. The statement:

...new myClass(i, j, k);...

can be implemented by the following:

...new #1            // Allocate uninitialized space for myClassdup               // Duplicate object on the operand stackiload_1           // Push iiload_2           // Push jiload_3           // Push kinvokespecial #5  // Invoke myClass.<init>...

This instruction sequence leaves the newly created and initialized object on top of the operand stack. (Additional examples of compilation to the instruction set of the Java Virtual Machine are given in§3 (Compiling for the Java Virtual Machine).)

The instance initialization method (§2.9.1) for classmyClass sees the new uninitialized object as itsthis argument in local variable 0. Before that method invokes another instance initialization method ofmyClass or its direct superclass onthis, the only operation the method can perform onthis is assigning fields declared withinmyClass.

When doing dataflow analysis on instance methods, the verifier initializes local variable 0 to contain an object of the current class, or, for instance initialization methods, local variable 0 contains a special type indicating an uninitialized object. After an appropriate instance initialization method is invoked (from the current class or its direct superclass) on this object, all occurrences of this special type on the verifier's model of the operand stack and in the local variable array are replaced by the current class type. The verifier rejects code that uses the new object before it has been initialized or that initializes the object more than once. In addition, it ensures that every normal return of the method has invoked an instance initialization method either in the class of this method or in the direct superclass.

Similarly, a special type is created and pushed on the verifier's model of the operand stack as the result of the Java Virtual Machine instructionnew. The special type indicates the instruction by which the class instance was created and the type of the uninitialized class instance created. When an instance initialization method declared in the class of the uninitialized class instance is invoked on that class instance, all occurrences of the special type are replaced by the intended type of the class instance. This change in type may propagate to subsequent instructions as the dataflow analysis proceeds.

The instruction number needs to be stored as part of the special type, as there may be multiple not-yet-initialized instances of a class in existence on the operand stack at one time. For example, the Java Virtual Machine instruction sequence that implements:

new InputStream(new Foo(), new InputStream("foo"))

may have two uninitialized instances ofInputStream on the operand stack at once. When an instance initialization method is invoked on a class instance, only those occurrences of the special type on the operand stack or in the local variable array that are the same object as the class instance are replaced.

4.10.2.5. Exceptions andfinally

To implement thetry-finally construct, a compiler for the Java programming language that generatesclass files with version number 50.0 or below may use the exception-handling facilities together with two special instructions:jsr ("jump to subroutine") andret ("return from subroutine"). Thefinally clause is compiled as a subroutine within the Java Virtual Machine code for its method, much like the code for an exception handler. When ajsr instruction that invokes the subroutine is executed, it pushes its return address, the address of the instruction after thejsr that is being executed, onto the operand stack as a value of typereturnAddress. The code for the subroutine stores the return address in a local variable. At the end of the subroutine, aret instruction fetches the return address from the local variable and transfers control to the instruction at the return address.

Control can be transferred to thefinally clause (thefinally subroutine can be invoked) in several different ways. If thetry clause completes normally, thefinally subroutine is invoked via ajsr instruction before evaluating the next expression. Abreak orcontinue inside thetry clause that transfers control outside thetry clause executes ajsr to the code for thefinally clause first. If thetry clause executes areturn, the compiled code does the following:

  1. Saves the return value (if any) in a local variable.

  2. Executes ajsr to the code for thefinally clause.

  3. Upon return from thefinally clause, returns the value saved in the local variable.

The compiler sets up a special exception handler, which catches any exception thrown by thetry clause. If an exception is thrown in thetry clause, this exception handler does the following:

  1. Saves the exception in a local variable.

  2. Executes ajsr to thefinally clause.

  3. Upon return from thefinally clause, rethrows the exception.

For more information about the implementation of thetry-finally construct, see§3.13.

The code for thefinally clause presents a special problem to the verifier. Usually, if a particular instruction can be reached via multiple paths and a particular local variable contains incompatible values through those multiple paths, then the local variable becomes unusable. However, afinally clause might be called from several different places, yielding several different circumstances:

  • The invocation from the exception handler may have a certain local variable that contains an exception.

  • The invocation to implementreturn may have some local variable that contains the return value.

  • The invocation from the bottom of thetry clause may have an indeterminate value in that same local variable.

The code for thefinally clause itself might pass verification, but after completing the updating all the successors of theret instruction, the verifier would note that the local variable that the exception handler expects to hold an exception, or that the return code expects to hold a return value, now contains an indeterminate value.

Verifying code that contains afinally clause is complicated. The basic idea is the following:

  • Each instruction keeps track of the list ofjsr targets needed to reach that instruction. For most code, this list is empty. For instructions inside code for thefinally clause, it is of length one. For multiply nestedfinally code (extremely rare!), it may be longer than one.

  • For each instruction and eachjsr needed to reach that instruction, a bit vector is maintained of all local variables accessed or modified since the execution of thejsr instruction.

  • When executing theret instruction, which implements a return from a subroutine, there must be only one possible subroutine from which the instruction can be returning. Two different subroutines cannot "merge" their execution to a singleret instruction.

  • To perform the data-flow analysis on aret instruction, a special procedure is used. Since the verifier knows the subroutine from which the instruction must be returning, it can find all thejsr instructions that call the subroutine and merge the state of the operand stack and local variable array at the time of theret instruction into the operand stack and local variable array of the instructions following thejsr. Merging uses a special set of values for local variables:

    • For any local variable that the bit vector (constructed above) indicates has been accessed or modified by the subroutine, use the type of the local variable at the time of theret.

    • For other local variables, use the type of the local variable before thejsr instruction.

4.11. Limitations of the Java Virtual Machine

The following limitations of the Java Virtual Machine are implicit in theclass file format:

  • The per-class or per-interface constant pool is limited to 65535 entries by the 16-bitconstant_pool_count field of theClassFile structure (§4.1). This acts as an internal limit on the total complexity of a single class or interface.

  • The number of fields that may be declared by a class or interface is limited to 65535 by the size of thefields_count item of theClassFile structure (§4.1).

    Note that the value of thefields_count item of theClassFile structure does not include fields that are inherited from superclasses or superinterfaces.

  • The number of methods that may be declared by a class or interface is limited to 65535 by the size of themethods_count item of theClassFile structure (§4.1).

    Note that the value of themethods_count item of theClassFile structure does not include methods that are inherited from superclasses or superinterfaces.

  • The number of direct superinterfaces of a class or interface is limited to 65535 by the size of theinterfaces_count item of theClassFile structure (§4.1).

  • The greatest number of local variables in the local variables array of a frame created upon invocation of a method (§2.6) is limited to 65535 by the size of themax_locals item of theCode attribute (§4.7.3) giving the code of the method, and by the 16-bit local variable indexing of the Java Virtual Machine instruction set.

    Note that values of typelong anddouble are each considered to reserve two local variables and contribute two units toward themax_locals value, so use of local variables of those types further reduces this limit.

  • The size of an operand stack in a frame (§2.6) is limited to 65535 values by themax_stack field of theCode attribute (§4.7.3).

    Note that values of typelong anddouble are each considered to contribute two units toward themax_stack value, so use of values of these types on the operand stack further reduces this limit.

  • The number of method parameters is limited to 255 by the definition of a method descriptor (§4.3.3), where the limit includes one unit forthis in the case of instance or interface method invocations.

    Note that a method descriptor is defined in terms of a notion of method parameter length in which a parameter of typelong ordouble contributes two units to the length, so parameters of these types further reduce the limit.

  • The length of field and method names, field and method descriptors, and other constant string values (including those referenced byConstantValue (§4.7.2) attributes) is limited to 65535 characters by the 16-bit unsignedlength item of theCONSTANT_Utf8_info structure (§4.4.7).

    Note that the limit is on the number of bytes in the encoding and not on the number of encoded characters. UTF-8 encodes some characters using two or three bytes. Thus, strings incorporating multibyte characters are further constrained.

  • The number of dimensions in an array is limited to 255 by the size of thedimensions opcode of themultianewarray instruction and by the constraints imposed on themultianewarray,anewarray, andnewarray instructions (§4.9.1,§4.9.2).


Prev   Next
Chapter 3. Compiling for the Java Virtual Machine Home Chapter 5. Loading, Linking, and Initializing

Legal Notice

[8]ページ先頭

©2009-2025 Movatter.jp