Flattened Heap Layouts for Value Objects

Changes to the Java® Virtual Machine Specification • Version 21-internal-adhoc.dlsmith.20230428

This document describes changes to the Java Virtual Machine Specification, as modified by the Better-defined JVM Class File Validation JEP, JVM Types Cleanup, and Value Objects, to support flattened heap layouts for value objects, a preview feature introduced by JEP 401.

Key changes include:

Changes are described with respect to existing sections of the JVM Specification. New text is indicated like this and deleted text is indicated like this. Explanation and discussion, as needed, is set aside in grey boxes.

Chapter 4: The class File Format

4.7 Attributes

Attributes are used in the ClassFile, field_info, method_info, Code_attribute, and record_component_info structures of the class 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, the attribute_name_index item must be a valid unsigned 16-bit index into the constant pool of the class. The constant_pool entry at attribute_name_index must be a CONSTANT_Utf8_info structure (4.4.7) which represents the name of the attribute. The value of the attribute_length item indicates the length of the subsequent information in bytes. The length does not include the initial six bytes that contain the attribute_name_index and attribute_length items.

29 attributes are predefined by this specification. They are listed three times, for ease of navigation:

Within the context of their use in this specification, that is, in the attributes tables of the structures of appropriately-versioned class files in which they appear, the names of these predefined attributes are reserved.

Any conditions on the presence of a predefined attribute in an attributes table are specified explicitly in the section which describes the attribute. If no conditions are specified, then the attribute may appear any number of times in an attributes table.

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

  1. Nine Eleven attributes are critical to correct interpretation of the class file by the Java Virtual Machine:

    • ConstantValue
    • Code
    • StackMapTable
    • BootstrapMethods
    • Module
    • ModulePackages
    • ModuleMainClass
    • NestHost
    • NestMembers
    • ImplicitCreation
    • NullRestricted

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

  2. 20 attributes are not critical to correct interpretation of the class file by the Java Virtual Machine, but contain metadata about the class 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"):

    • Exceptions
    • InnerClasses
    • EnclosingMethod
    • Synthetic
    • Signature
    • Record
    • SourceFile
    • SourceDebugExtension
    • LineNumberTable
    • LocalVariableTable
    • LocalVariableTypeTable
    • Deprecated
    • RuntimeVisibleAnnotations
    • RuntimeInvisibleAnnotations
    • RuntimeVisibleParameterAnnotations
    • RuntimeInvisibleParameterAnnotations
    • RuntimeVisibleTypeAnnotations
    • RuntimeInvisibleTypeAnnotations
    • AnnotationDefault
    • MethodParameters

    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. Predefined class file attributes (by section)

Attribute Section class file Java SE
ConstantValue 4.7.2 45.3 1.0.2
Code 4.7.3 45.3 1.0.2
StackMapTable 4.7.4 50.0 6
Exceptions 4.7.5 45.3 1.0.2
InnerClasses 4.7.6 45.3 1.1
EnclosingMethod 4.7.7 49.0 5.0
Synthetic 4.7.8 45.3 1.1
Signature 4.7.9 49.0 5.0
SourceFile 4.7.10 45.3 1.0.2
SourceDebugExtension 4.7.11 49.0 5.0
LineNumberTable 4.7.12 45.3 1.0.2
LocalVariableTable 4.7.13 45.3 1.0.2
LocalVariableTypeTable 4.7.14 49.0 5.0
Deprecated 4.7.15 45.3 1.1
RuntimeVisibleAnnotations 4.7.16 49.0 5.0
RuntimeInvisibleAnnotations 4.7.17 49.0 5.0
RuntimeVisibleParameterAnnotations 4.7.18 49.0 5.0
RuntimeInvisibleParameterAnnotations 4.7.19 49.0 5.0
RuntimeVisibleTypeAnnotations 4.7.20 52.0 8
RuntimeInvisibleTypeAnnotations 4.7.21 52.0 8
AnnotationDefault 4.7.22 49.0 5.0
BootstrapMethods 4.7.23 51.0 7
MethodParameters 4.7.24 52.0 8
Module 4.7.25 53.0 9
ModulePackages 4.7.26 53.0 9
ModuleMainClass 4.7.27 53.0 9
NestHost 4.7.28 55.0 11
NestMembers 4.7.29 55.0 11
Record 4.7.30 60.0 16
ImplicitCreation 4.7.31 65.65535 21
NullRestricted 4.7.32 65.65535 21

Table 4.7-B. Predefined class file attributes (by class file format)

Attribute class file Java SE Section
ConstantValue 45.3 1.0.2 4.7.2
Code 45.3 1.0.2 4.7.3
Exceptions 45.3 1.0.2 4.7.5
SourceFile 45.3 1.0.2 4.7.10
LineNumberTable 45.3 1.0.2 4.7.12
LocalVariableTable 45.3 1.0.2 4.7.13
InnerClasses 45.3 1.1 4.7.6
Synthetic 45.3 1.1 4.7.8
Deprecated 45.3 1.1 4.7.15
EnclosingMethod 49.0 5.0 4.7.7
Signature 49.0 5.0 4.7.9
SourceDebugExtension 49.0 5.0 4.7.11
LocalVariableTypeTable 49.0 5.0 4.7.14
RuntimeVisibleAnnotations 49.0 5.0 4.7.16
RuntimeInvisibleAnnotations 49.0 5.0 4.7.17
RuntimeVisibleParameterAnnotations 49.0 5.0 4.7.18
RuntimeInvisibleParameterAnnotations 49.0 5.0 4.7.19
AnnotationDefault 49.0 5.0 4.7.22
StackMapTable 50.0 6 4.7.4
BootstrapMethods 51.0 7 4.7.23
RuntimeVisibleTypeAnnotations 52.0 8 4.7.20
RuntimeInvisibleTypeAnnotations 52.0 8 4.7.21
MethodParameters 52.0 8 4.7.24
Module 53.0 9 4.7.25
ModulePackages 53.0 9 4.7.26
ModuleMainClass 53.0 9 4.7.27
NestHost 55.0 11 4.7.28
NestMembers 55.0 11 4.7.29
Record 60.0 16 4.7.30
ImplicitCreation 65.65535 21 4.7.31
NullRestricted 65.65535 21 4.7.32

Table 4.7-C. Predefined class file attributes (by location)

Attribute Location class file
SourceFile ClassFile 45.3
InnerClasses ClassFile 45.3
EnclosingMethod ClassFile 49.0
SourceDebugExtension ClassFile 49.0
BootstrapMethods ClassFile 51.0
Module, ModulePackages, ModuleMainClass ClassFile 53.0
NestHost, NestMembers ClassFile 55.0
Record ClassFile 60.0
ImplicitCreation ClassFile 65.65535
ConstantValue field_info 45.3
NullRestricted field_info 65.65535
Code method_info 45.3
Exceptions method_info 45.3
RuntimeVisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations method_info 49.0
AnnotationDefault method_info 49.0
MethodParameters method_info 52.0

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

Attribute Location class file
Synthetic ClassFile, field_info, method_info 45.3
Deprecated ClassFile, field_info, method_info 45.3
Signature ClassFile, field_info, method_info, record_component_info 49.0
RuntimeVisibleAnnotations, RuntimeInvisibleAnnotations ClassFile, field_info, method_info, record_component_info 49.0
LineNumberTable Code 45.3
LocalVariableTable Code 45.3
LocalVariableTypeTable Code 49.0
StackMapTable Code 50.0
RuntimeVisibleTypeAnnotations, RuntimeInvisibleTypeAnnotations ClassFile, field_info, method_info, Code, record_component_info 52.0

4.7.31 The ImplicitCreation Attribute

The ImplicitCreation attribute is a fixed-length attribute in the attributes table of a ClassFile structure in a version 65.65535 class file. The ImplicitCreation attribute authorizes implicit instance creation of a non-abstract value class beyond normal usage of the aconst_init and withfield instructions.

There must be no more than one ImplicitCreation attribute in the attributes table of a ClassFile structure representing a non-abstract value class. There must not be an ImplicitCreation attribute in the attributes table of any other ClassFile structure representing a class, interface, or module.

The ImplicitCreation attribute must have the following format:

ImplicitCreation_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 implicit_creation_flags;
}

The items of the ImplicitCreation_attribute structure are as follows:

attribute_name_index

The value of the attribute_name_index item is an index into the constant_pool table. The constant_pool entry at that index is a CONSTANT_Utf8_info structure (4.4.7) representing the string "ImplicitCreation".

attribute_length

The value of the attribute_length item must be two.

implicit_creation_flags

The value of the implicit_creation_flags item is a mask of flags used to authorize implicit creation of class instances beyond normal usage of the aconst_init and withfield instructions.

The flags are specified in Table 4.7.31-A.

Table 4.7.31-A. Implicit creation flags

Flag Name Value Interpretation
ACC_DEFAULT 0x0001 Allows use of the initial instance as a default value.
ACC_NON_ATOMIC 0x0002 Allows non-atomic updates to create new instances from the field values of existing instances.

All bits of the implicit_creation_flags item not assigned in Table 4.7.31-A are reserved for future use. They should be set to zero in generated class files and should be ignored by Java Virtual Machine implementations.

4.7.32 The NullRestricted Attribute

The NullRestricted attribute is a fixed-length attribute in the attributes table of a field_info structure in a version 65.65535 class file. The NullRestricted attribute indicates that the field has a null-restricted type, requiring the field to be initialized to the initial instance of the field's class () and preventing any attempts to store null (6.5.putfield, 6.5.putstatic).

There must be no more than one NullRestricted attribute in the attributes table of a field_info structure. There must not be a NullRestricted attribute in the attributes table of a field_info structure whose descriptor_index references a primitive type or an array type.

The descriptor_index of the field should name a value class that has an ImplicitCreation attribute with its ACC_DEFAULT flag is set.

The NullRestricted attribute must have the following format:

NullRestricted_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
}

The items of the NullRestricted_attribute structure are as follows:

attribute_name_index

The value of the attribute_name_index item is an index into the constant_pool table. The constant_pool entry at that index is a CONSTANT_Utf8_info structure (4.4.7) representing the string "NullRestricted".

attribute_length

The value of the attribute_length item must be zero.

Chapter 5: Loading, Linking, and Initializing

5.3 Creation and Loading

5.3.5 Deriving a Class from a class File Representation

The following steps are used to derive a Class object for the nonarray class or interface C denoted by N using loader L from a purported representation in class file format.

  1. First, the Java Virtual Machine determines whether the attempt to derive a class or interface named N for class loader L is invalid. If so, loading throws a LinkageError.

    An attempt to derive a class or interface named N for class loader L is invalid if one of the following are true:

    • L has already been recorded as as an initiating loader of a class or interface named N.

    • L is not the bootstrap class loader (5.3) and N is the reserved name java/lang/Object.

    The second case, combined with restrictions in 4.1, ensures that there is only one root of the class hierarchy, and the name java/lang/Object can reliably be used to refer to it.

    The Java SE API enforces additional security restrictions that prevent unauthorized attempts to load classes in certain packages, including java.*.

  2. Otherwise, the Java Virtual Machine attempts to parse the purported representation. However, the purported representation may not in fact be a valid representation of C.

    This phase of loading must detect the following errors:

    • If the purported representation provides a major and minor version number in its 5th through 8th bytes (4.1), but the version number is not supported by this Java Virtual Machine implementation, loading throws an instance of UnsupportedClassVersionError.

      UnsupportedClassVersionError, a subclass of ClassFormatError, was introduced to enable easy identification of a ClassFormatError caused by an attempt to load a class whose representation uses an unsupported version of the class file format. In JDK 1.1 and earlier, an instance of NoClassDefFoundError or ClassFormatError was thrown in case of an unsupported version, depending on whether the class was being loaded by the system class loader or a user-defined class loader.

    • Otherwise, if the purported representation is not a valid class file ([4]), loading throws an instance of ClassFormatError.

    • Otherwise, if the purported representation does not actually represent a class or interface named N, loading throws an instance of NoClassDefFoundError or an instance of one of its subclasses.

      This occurs when the purported representation has either a this_class item which specifies a name other than N, or an access_flags item which has the ACC_MODULE flag set.

  3. If C has a direct superclass, the symbolic reference from C to its direct superclass is resolved using the algorithm of 5.4.3.1. Only Object has no direct superclass.

    Note that if C is an interface, its direct superclass is the class Object (4.1). The symbolic reference to Object is resolved just like a reference to any other class.

    Any exceptions that can be thrown due to class or interface resolution can be thrown as a result of this phase of loading. In addition, this phase of loading must detect the following errors:

    • If any of the superclasses of C is C itself, loading throws a ClassCircularityError.

    • Otherwise, if the class or interface named as the direct superclass of C is in fact an interface or a final class, loading throws an IncompatibleClassChangeError.

    • Otherwise, if C is an identity class and any superclass of C is a value class, or C is a value class and any superclass of C is an identity class, loading throws an IncompatibleClassChangeError.

    • Otherwise, if C is a class and some instance method declared in C can override (5.4.5) a final instance method declared in a superclass of C, loading throws an IncompatibleClassChangeError.

  4. If C has any direct superinterfaces, the symbolic references from C to its direct superinterfaces are resolved using the algorithm of 5.4.3.1.

    Any exceptions that can be thrown due to class or interface resolution can be thrown as a result of this phase of loading. In addition, this phase of loading must detect the following errors:

    • If any of the superinterfaces of C is C itself, loading throws a ClassCircularityError.

    • Otherwise, if any of the classes or interfaces named as direct superinterfaces of C is not in fact an interface, loading throws an IncompatibleClassChangeError.

    • Otherwise, if C, one of its superclasses, or one of its superinterfaces is an identity class or an identity interface, and some other of C, one of its superclasses, or one of its superinterfaces is a value class or a value interface, loading throws an IncompatibleClassChangeError.

  1. If C is a value class and has an ImplicitCreation attribute with its ACC_DEFAULT flag set, then for each non-static field of C declared with a NullRestricted attribute, the type is resolved, as if by resolution of an unresolved symbolic reference to a class or interface (5.4.3.1).

    Any exceptions that can be thrown due to class or interface resolution can be thrown as a result of this phase of loading. In addition, this phase of loading must detect the following errors:

    • If loading the class or interface named by the field's type depends recursively on loading C itself, loading throws a ClassCircularityError.

    • Otherwise, the class or interface named by the field's type must be a value class with an ImplicitCreation attribute whose ACC_DEFAULT flag is set. If not, loading throws an IncompatibleClassChangeError.

    If C is a value class that supports implicit initialization of fields and arrays, then the initial instance of C must be well-formed and must not attempt to contain itself. Otherwise, we can't allow C to be successfully loaded, or operations like Array.newInstance would have undefined behavior. Additional validation of other null-restricted fields will take place during linking ([5.4]).

  1. The Java Virtual Machine marks C as having L as its defining class loader and records that L is an initiating loader of C (5.3.4).

5.4 Linking

5.4.2 Preparation

Preparation involves creating the static fields for a class or interface and initializing such fields to their default values (2.3, 2.4). This does not require the execution of any Java Virtual Machine code; explicit initializers for static fields are executed as part of initialization (5.5), not preparation.

Preparation performs linking actions necessary for a class or interface to be able to execute its class or interface initialization method (2.9.2) during initialization (5.5).

To prepare a class or interface C, the Java Virtual Machine imposes constraints on field and method descriptors (4.3), as follows:

  1. For each field of C declared with a NullRestricted attribute, the type of the field is resolved, as if by resolution of an unresolved symbolic reference to a class or interface (5.4.3.1).

    Any exception that can be thrown as a result of failure of class or interface resolution can thus be thrown as a result of failure of preparation.

    The resolved type must be of a value class with an ImplicitCreation attribute whose ACC_DEFAULT flag set. If not, preparation fails with an IncompatibleClassChangeError.

  1. Let L1 be the defining loader of C. For each instance method m declared in C that can override (5.4.5) an instance method declared in a superclass or superinterface <D, L2>, for each class or interface name N mentioned by the descriptor of m (4.3.3), the Java Virtual Machine imposes the loading constraint NL1 = NL2.

  2. For each instance method m declared in a superinterface <I, L3> of C, if C does not itself declare an instance method that can override m, then a method is selected (5.4.6) with respect to C and the method m in <I, L3>. Let <D, L2> be the class or interface that declares the selected method. For each class or interface name N mentioned by the descriptor of m, the Java Virtual Machine imposes the loading constraint NL2 = NL3.

If the class or interface satisfies these constraints, the Java Virtual Machine creates and initializes its static fields. The initial value of a field declared with a NullRestricted attribute is the initial instance of the field's class (6.5.aconst_init). The initial value of a field of a primitive type is the default value of the type (2.3). The initial value of any other field is null.

Preparation may occur at any time following creation but must be completed prior to initialization.

5.5 Initialization

Design discussion: this section specifies the initialization of value classes named by null-restricted reference types in the anewarray and multianewarray instructions, as a prerequesite to creating an initial instance.

We could refine this behavior by:

Initialization of a class or interface consists of executing its class or interface initialization method (2.9.2).

A class or interface C may be initialized only as a result of:

Prior to initialization, a class or interface must be linked, that is, verified, prepared, and optionally resolved.

Because the Java Virtual Machine is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time. There is also the possibility that initialization of a class or interface may be requested recursively as part of the initialization of that class or interface. The implementation of the Java Virtual Machine is responsible for taking care of synchronization and recursive initialization by using the following procedure. It assumes that the class or interface has already been verified and prepared, and that the class or interface contains state that indicates one of four situations:

For each class or interface C, there is a unique initialization lock LC. The mapping from C to LC is left to the discretion of the Java Virtual Machine implementation. For example, LC could be the Class object for C, or the monitor associated with that Class object. The procedure for initializing C is then as follows:

  1. Synchronize on the initialization lock, LC, for C. This involves waiting until the current thread can acquire LC.

  2. If C indicates that initialization is in progress for C by some other thread, then release LC and block the current thread until informed that the in-progress initialization has completed, at which time repeat this procedure.

    Thread interrupt status is unaffected by execution of the initialization procedure.

  3. If C indicates that initialization is in progress for C by the current thread, then this must be a recursive request for initialization. Release LC and complete normally.

  4. If C indicates that it has already been initialized, then no further action is required. Release LC and complete normally.

  5. If C is in an erroneous state, then initialization is not possible. Release LC and throw a NoClassDefFoundError.

  6. Otherwise, record the fact that initialization of the Class object for C is in progress by the current thread, and release LC.

    Then, initialize each final static field of C with the constant value in its ConstantValue attribute (4.7.2), in the order the fields appear in the ClassFile structure.

  7. Next, if C is a class rather than an interface, then let SC be its superclass and let SI1, ..., SIn be all superinterfaces of C (whether direct or indirect) that declare at least one non-abstract, non-static method. The order of superinterfaces is given by a recursive enumeration over the superinterface hierarchy of each interface directly implemented by C. For each interface I directly implemented by C (in the order of the interfaces array of C), the enumeration recurs on I's superinterfaces (in the order of the interfaces array of I) before returning I.

    For each S in the list [ SC, SI1, ..., SIn ], if S has not yet been initialized, then recursively perform this entire procedure for S. If necessary, verify and prepare S first.

    If the initialization of S completes abruptly because of a thrown exception, then acquire LC, label C as erroneous, notify all waiting threads, release LC, and complete abruptly, throwing the same exception that resulted from initializing S.

  8. Next, for each field of C (in the order of the fields array of C), if the field is declared with a NullRestricted attribute, recursively perform this entire procedure for the class, F, named by the field's type. If necessary, verify and prepare F first.

    Initialization of F is necessary because the field's initial value is an instance of F.

    If the initialization of F completes abruptly because of a thrown exception, then acquire LC, label C as erroneous, notify all waiting threads, release LC, and complete abruptly, throwing the same exception that resulted from initializing F.

  9. Next, determine whether assertions are enabled for C by querying its defining class loader.

  10. Next, if C declares a class or interface initialization method, execute that method.

  11. If the execution of the class or interface initialization method completes normally, then acquire LC, label the Class object for C as fully initialized, notify all waiting threads, release LC, and complete this procedure normally.

  12. Otherwise, the class or interface initialization method must have completed abruptly by throwing some exception E. If the class of E is not Error or one of its subclasses, then create a new instance of the class ExceptionInInitializerError with E as the argument, and use this object in place of E in the following step. If a new instance of ExceptionInInitializerError cannot be created because an OutOfMemoryError occurs, then use an OutOfMemoryError object in place of E in the following step.

  13. Acquire LC, label C as erroneous, notify all waiting threads, release LC, and complete this procedure abruptly with reason E or its replacement as determined in the previous step.

A Java Virtual Machine implementation may optimize this procedure by eliding the lock acquisition in step 1 (and release in step 4/5) when it can determine that the initialization of the class has already completed, provided that, in terms of the Java memory model, all happens-before orderings (JLS §17.4.5) that would exist if the lock were acquired, still exist when the optimization is performed.

Chapter 6: The Java Virtual Machine Instruction Set

6.5 Instructions

aastore

Operation

Store into reference array

Format

aastore

Forms

aastore = 83 (0x53)

Operand Stack

..., arrayref, index, value

...

Description

The arrayref must be of type reference and must refer to an array whose components are of type reference. The index must be of type int, and value must be of type reference. The arrayref, index, and value are popped from the operand stack.

If value is null and the component type of the array referenced by arrayref is not null-restricted, then value is stored as the component of the array at index.

Otherwise, value is non-null. If value is a non-null value of the component type of the array referenced by arrayref, then value is stored as the component of the array at index.

Whether value is a value of the array component type is determined according to the rules given for checkcast.

Run-time Exceptions

If arrayref is null, aastore throws a NullPointerException.

Otherwise, if index is not within the bounds of the array referenced by arrayref, the aastore instruction throws an ArrayIndexOutOfBoundsException.

Otherwise, if value is null and the component type of the array referenced by arrayref is a null-restricted reference type, aastore throws a NullPointerException.

Otherwise, if the non-null value is not a value of the array component type, aastore throws an ArrayStoreException.

aconst_init

Operation

Push initial instance of a value class

Format

aconst_init
indexbyte1
indexbyte2

Forms

aconst_init = 203 (0xcb)

Operand Stack

...

..., objectref

Description

The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a class or interface.

The referenced class or interface is resolved (5.4.3.1). The resolved class or interface must be a value class that belongs to the same nest as the current class, according to the nestmate test in 5.4.4.

The referenced value class is initialized if it has not already been initialized (5.5).

A reference to an instance of the value class, with instance variable values set to the default initial values of their types (2.3, 2.4), is pushed onto the operand stack. Memory for the class instance may be newly allocated from the garbage-collected heap, or may have been allocated previously. The initial value of any instance field declared with a NullRestricted attribute is the initial instance of the field's class. The initial value of any instance field of a primitive type is the default value of the type (2.3). The initial value of any other instance field is null.

Linking Exceptions

During resolution of the symbolic reference to the class or interface, any of the exceptions documented in 5.4.3.1 can be thrown.

If the referenced class or interface is abstract or is not a value class, aconst_init fails with an IncompatibleClassChangeError.

Otherwise, if the referenced value class does not belong to the same nest as the current class, any of the exceptions pertaining to the nestmate test (5.4.4) may be thrown.

Run-time Exception

Otherwise, if execution of this aconst_init instruction causes initialization of the referenced class, aconst_init may throw an Error as detailed in 5.5.

Notes

The value object produced by aconst_init may be referred to as the initial instance of the given value class.

The aconst_init instruction is similar to the new instruction. But unlike new, the aconst_init instruction does not necessarily allocate a new object on the garbage-collected heap; instead, a previously-created class instance can be used. Also unlike new, the class instance provided by aconst_init is completely initialized—there is no need to invoke an instance initialization method.

The aconst_init instruction may not be used on value classes declared outside of the current class's nest. Those classes may declare value class instance creation methods (2.9.4) or other mechanisms to provide classes outside of the nest with a controlled path for instance creation.

The withfield instruction is used to create value class instances other than the initial instance.

anewarray

Operation

Create new array of reference

Format

anewarray
indexbyte1
indexbyte2

Forms

anewarray = 189 (0xbd)

Operand Stack

..., count

..., arrayref

Description

The count must be of type int. It is popped off the operand stack. The count represents the number of components of the array to be created. The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a class, interface, or array type.

The named class, interface, or array type is resolved (5.4.3.1).

A new array with component type given by the resolved class, interface, or array type, of length count, is allocated from the garbage-collected heap, and a reference arrayref to this new array object is pushed onto the operand stack.

All components of the new array are initialized to null, the default value for reference types (2.4).

Linking Exceptions

During resolution of the symbolic reference to the class, interface, or array type, any of the exceptions documented in 5.4.3.1 can be thrown.

Run-time Exceptions

Otherwise, if count is less than zero, the anewarray instruction throws a NegativeArraySizeException.

Notes

The anewarray instruction is used to create a single dimension of an array of object references or part of a multidimensional array.

new

Operation

Create new identity object

Format

new
indexbyte1
indexbyte2

Forms

new = 187 (0xbb)

Operand Stack

...

..., objectref

Description

The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a class or interface. The named class or interface is resolved (5.4.3.1) and should result in a non-abstract identity class or the class Object. The named class is initialized if it has not already been initialized (5.5).

Memory for a new instance of that class is allocated from the garbage-collected heap , and the instance variables of the new object are initialized to the default initial values of their types (2.3, 2.4). The initial value of any instance field declared with the NullRestricted attribute is the initial instance of the field's class (6.5.aconst_init). The initial value of any instance field of a primitive type is the default value of the type (2.3). The initial value of any other instance field is null.

The objectref, a reference to the instance, is pushed onto the operand stack.

Linking Exceptions

During resolution of the symbolic reference to the class or interface, any of the exceptions documented in 5.4.3.1 can be thrown.

Otherwise, if the symbolic reference to the class or interface resolves to an interface, an abstract class, or a value class, new throws an InstantiationError.

Run-time Exception

Otherwise, if execution of this new instruction causes initialization of the referenced class, new may throw an Error as detailed in 5.5.

Notes

The new instruction does not completely create a new instance; instance creation is not completed until an instance initialization method (2.9.1) has been invoked on the uninitialized instance.

putfield

Operation

Set field in object

Format

putfield
indexbyte1
indexbyte2

Forms

putfield = 181 (0xb5)

Operand Stack

..., objectref, value

...

Description

The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a field (5.1), which gives the name and descriptor of the field as well as a symbolic reference to the class, interface, or array type in which the field is to be found. The referenced field is resolved (5.4.3.2).

The type of a value stored by a putfield instruction must be compatible with the descriptor of the referenced field (4.3.2). If the field descriptor type is boolean, byte, char, short, or int, then the value must be an int. If the field descriptor type is float, long, or double, then the value must be a float, long, or double, respectively. If the field descriptor type is a reference type, then the value must be a value of the field descriptor type. If the field is final, it must be declared in the current class, and the instruction must occur in an instance initialization method of the current class (2.9.1).

The value and objectref are popped from the operand stack.

The objectref must be of type reference but not an array type.

If the value is of type int and the field descriptor type is boolean, then the int value is narrowed by taking the bitwise AND of value and 1, resulting in value'. Otherwise, the value undergoes value set conversion (2.8.3), resulting in value'.

The referenced field in objectref is set to value'.

Linking Exceptions

During resolution of the symbolic reference to the field, any of the exceptions pertaining to field resolution (5.4.3.2) can be thrown.

Otherwise, if the resolved field is a static field, putfield throws an IncompatibleClassChangeError.

Otherwise, if the resolved field is final, it must be declared in the current class, and the instruction must occur in an instance initialization method of the current class. Otherwise, an IllegalAccessError is thrown.

Run-time Exception

Otherwise, if objectref is null, or if the value to store is null and the resolved field is declared with a NullRestricted attribute, the putfield instruction throws a NullPointerException.

putstatic

Operation

Set static field in class

Format

putstatic
indexbyte1
indexbyte2

Forms

putstatic = 179 (0xb3)

Operand Stack

..., value

...

Description

The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a field (5.1), which gives the name and descriptor of the field as well as a symbolic reference to the class, interface, or array reference type in which the field is to be found. The referenced field is resolved (5.4.3.2).

On successful resolution of the field, the class or interface that declared the resolved field is initialized if that class or interface has not already been initialized (5.5).

The type of a value stored by a putstatic instruction must be compatible with the descriptor of the referenced field (4.3.2). If the field descriptor type is boolean, byte, char, short, or int, then the value must be an int. If the field descriptor type is float, long, or double, then the value must be a float, long, or double, respectively. If the field descriptor type is a reference type, then the value must be a value of the field descriptor type. If the field is final, it must be declared in the current class or interface, and the instruction must occur in the class or interface initialization method of the current class or interface (2.9.2).

The value is popped from the operand stack.

If the value is of type int and the field descriptor type is boolean, then the int value is narrowed by taking the bitwise AND of value and 1, resulting in value'. Otherwise, the value undergoes value set conversion (2.8.3), resulting in value'.

The referenced field in the class or interface is set to value'.

Linking Exceptions

During resolution of the symbolic reference to the class or interface field, any of the exceptions pertaining to field resolution (5.4.3.2) can be thrown.

Otherwise, if the resolved field is not a static (class) field or an interface field, putstatic throws an IncompatibleClassChangeError.

Otherwise, if the resolved field is final, it must be declared in the current class or interface, and the instruction must occur in the class or interface initialization method of the current class or interface. Otherwise, an IllegalAccessError is thrown.

Run-time Exception

Otherwise, if execution of this putstatic instruction causes initialization of the referenced class or interface, putstatic may throw an Error as detailed in 5.5.

Otherwise, if the value to store is null and the resolved field is declared with a NullRestricted attribute, the putstatic instruction throws a NullPointerException.

Notes

A putstatic instruction may be used only to set the value of an interface field on the initialization of that field. Interface fields may be assigned to only once, on execution of an interface variable initialization expression when the interface is initialized (5.5, JLS §9.3.1).

withfield

Operation

Duplicate value object with new field value

Format

withfield
indexbyte1
indexbyte2

Forms

withfield = 204 (0xcc)

Operand Stack

..., objectref1, value

..., objectref2

Description

The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool entry at the index must be a symbolic reference to a field (5.1), which gives the name and descriptor of the field as well as a symbolic reference to the type in which the field is to be found. The referenced field is resolved (5.4.3.2).

The objectref1 must be an instance of a value class, and the resolved field must be declared by that class.

The type of a value stored by a withfield instruction must be compatible with the descriptor of the referenced field (4.3.2). If the field descriptor type is boolean, byte, char, short, or int, then the value must be an int. If the field descriptor type is float, long, or double, then the value must be a float, long, or double, respectively. If the field descriptor type is a reference type, then the value must be of a type that is assignment compatible (JLS §5.2) with the field descriptor type.

The resolved field must be declared by a class that belongs to the same nest as the current class, according to the nestmate test in 5.4.4.

The value and objectref1 are popped from the operand stack.

If the value is of type int and the field descriptor type is boolean, then the int value is narrowed by taking the bitwise AND of value and 1, resulting in value'. Otherwise, the value undergoes value set conversion (2.8.3), resulting in value'.

A reference to an instance of the value class, objectref2, is pushed onto the operand stack. The referenced field in objectref2 is set to value'. Every other instance field in objectref2 is set to the corresponding field's value in objectref1. Memory for objectref2 may be newly allocated from the garbage-collected heap, or may have been allocated previously.

Linking Exceptions

During resolution of the symbolic reference to the field, any of the exceptions pertaining to field resolution (5.4.3.2) can be thrown.

Otherwise, if the resolved field is a static field, or the resolved field is not declared by a non-abstract value class, withfield throws an IncompatibleClassChangeError.

Otherwise, if the resolved field is not declared by a class that belongs to the same nest as the current class, any of the exceptions pertaining to the nestmate test (5.4.4) may be thrown.

Run-time Exception

Otherwise, if objectref1 is null, or if the value to store is null and the resolved field is declared with a NullRestricted attribute, the withfield instruction throws a NullPointerException.

Notes

The withfield instruction may not be used on value classes declared outside of the current class's nest. Those classes may declare value class instance creation methods (2.9.4) or other mechanisms to provide classes outside of the nest with a controlled path for instance creation.