JEP 306 JVMS Changes

Changes to the Java Virtual Machine Specification Version 17-internal+0-adhoc.darcy.open

This document describes changes to the Java Virtual Machine Specification to support JEP 306.

Changes are described with respect to existing sections of the JVMS. 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 2: The Structure of the Java Virtual Machine

2.3 Primitive Types and Values

The primitive data types supported by the Java Virtual Machine are the numeric types, the boolean type (2.3.4), and the returnAddress type (2.3.3).

The numeric types consist of the integral types (2.3.1) and the floating-point types (2.3.2).

The integral types are:

The floating-point types are:

The values of the boolean type encode the truth values true and false, and the default value is false.

The First Edition of The Java® Virtual Machine Specification did not consider boolean to be a Java Virtual Machine type. However, boolean values do have limited support in the Java Virtual Machine. The Second Edition of The Java® Virtual Machine Specification clarified the issue by treating boolean as a type.

The values of the returnAddress type are pointers to the opcodes of Java Virtual Machine instructions. Of the primitive types, only the returnAddress type is not directly associated with a Java programming language type.

2.3.2 Floating-Point Types, Value Sets, and Values

Note to readers: this section is very similar in structure and content to JLS 4.2.3.

The floating-point types are float and double, which are conceptually associated with the 32-bit binary32 and 64-bit binary64 floating-point formats for IEEE 754 values and operations, as specified in the IEEE 754 Standard (JLS §1.7).

In Java SE 15 and later, the Java Virtual Machine uses the 2019 version of the IEEE 754 Standard. Prior to Java SE 15, the Java Virtual Machine used the 1985 version of the IEEE 754 Standard, where the binary32 format was known as the single format and the binary64 format was known as the double format.

IEEE 754 includes not only positive and negative sign-magnitude numbers, but also positive and negative zeros, positive and negative infinities, and a special Not-a-Number value (hereafter abbreviated as "NaN"). The NaN value is used to represent the result of certain invalid operations such as dividing zero by zero.

Every implementation of the Java Virtual Machine is required to support two standard sets of floating-point values, called the float value set and the double value set. In addition, an implementation of the Java Virtual Machine may, at its option, support either or both of two extended-exponent floating-point value sets, called the float-extended-exponent value set and the double-extended-exponent value set. These extended-exponent value sets may, under certain circumstances, be used instead of the standard value sets to represent the values of type float or double.

The finite nonzero values of any binary floating-point value settype can all be expressed in the form s m 2^(e\ −\ N\ +\ 1)^, where s is +1 or −1, m is a positive integer less than 2N, and e is an integer between Emin = −(2K−1−2) and Emax = 2K−1−1, inclusive, and where N and K are parameters that depend on the value setassociated format. Some values can be represented in this form in more than one way; for example, supposing that a value v in a value set might be represented in this form using certain values for s, m, and e, then if it happened that m were even and e were less than 2K-1, one could halve m and increase e by 1 to produce a second representation for the same value v. A representation in this form is called normalized if m 2N-1; otherwise the representation is said to be subnormal. If a value in a value settype cannot be represented in such a way that m 2N-1, then the value is said to be a subnormal value, because its magnitude is below the magnitude of the smallest normalized value.

The constraints on the parameters N and K (and on the derived parameters Emin and Emax) for float and doublethe two required and two optional floating-point value sets are summarized in Table 2.3.2-A.

Table 2.3.2-A. Floating-point value set parameters

Parameter float float-extended-exponent double double-extended-exponent
N 24 24 53 53
K 8 11 11 15
Emax +127 +1023 +1023 +16383
Emin -126 -1022 -1022 -16382

Table 2.3.2-A. Floating-point value set parameters

Parameter float double
N 24 53
K 8 11
Emax +127 +1023
Emin -126 -1022

Where one or both extended-exponent value sets are supported by an implementation, then for each supported extended-exponent value set there is a specific implementation-dependent constant K, whose value is constrained by Table 2.3.2-A; this value K in turn dictates the values for Emin and Emax.

Each of the four value sets includes not only the finite nonzero values that are ascribed to it above, but also the five values: positive zero, negative zero, positive infinity, negative infinity, and NaN.

Note that the constraints in Table 2.3.2-A are designed so that every element of the float value set is necessarily also an element of the float-extended-exponent value set, the double value set, and the double-extended-exponent value set. Likewise, each element of the double value set is necessarily also an element of the double-extended-exponent value set. Each extended-exponent value set has a larger range of exponent values than the corresponding standard value set, but does not have more precision.

The elements of the float value set are exactly the values that can be represented using the binary32 floating-point format defined by IEEE 754, except that there is only one NaN value (IEEE 754 specifies 224-2 distinct NaN values). The elements of the double value set are exactly the values that can be represented using the binary64 floating-point format defined by IEEE 754, except that there is only one NaN value (IEEE 754 specifies 253-2 distinct NaN values). Note, however, that the elements of the float-extended-exponent and double-extended-exponent value sets defined here do not correspond to the values that can be represented using, respectively, the binary32 extended and binary64 extended floating-point formats defined by IEEE 754. This specification does not mandate a specific representation for the values of the floating-point value sets except where floating-point values must be represented in the class file format (4.4.4, 4.4.5).

The float, float-extended-exponent, double, and double-extended-exponent value sets are not types. It is always correct for an implementation of the Java Virtual Machine to use an element of the float value set to represent a value of type float; however, it may be permissible in certain contexts for an implementation to use an element of the float-extended-exponent value set instead. Similarly, it is always correct for an implementation to use an element of the double value set to represent a value of type double; however, it may be permissible in certain contexts for an implementation to use an element of the double-extended-exponent value set instead.

Except for NaNs, values of the floating-point value setsfloating-point values are ordered. When arranged from smallest to largest, they are negative infinity, negative finite values, positive and negative zero, positive finite values, and positive infinity.

Floating-point positive zero and floating-point negative zero compare as equal, but there are other operations that can distinguish them; for example, dividing 1.0 by 0.0 produces positive infinity, but dividing 1.0 by -0.0 produces negative infinity.

NaNs are unordered, so numerical comparisons and tests for numerical equality have the value false if either or both of their operands are NaN. In particular, a test for numerical equality of a value against itself has the value false if and only if the value is NaN. A test for numerical inequality has the value true if either operand is NaN.

2.8 Floating-Point Arithmetic

The full content of section (2.8.3) is deleted. The content previous in sections (2.8.1) and (2.8.2) is edited and incoroprated into 2.8 itself.

The Java Virtual Machine incorporates a subset of the floating-point arithmetic specified in the IEEE 754 Standard (JLS §1.7).

In Java SE 15 and later, the Java Virtual Machine uses the 2019 version of the IEEE 754 Standard. Prior to Java SE 15, the Java Virtual Machine used the 1985 version of the IEEE 754 Standard, where the binary32 format was known as the single format and the binary64 format was known as the double format.

Many of the Java Virtual Machine instructions for arithmetic (2.11.3) and type conversion (2.11.4) work with floating-point numbers. Java Virtual Machine These instructions on floating-point numbers behave as specified in IEEE 754, correspond to IEEE 754 operations [Table 2.8-A], with the exception of certain instructions described below.

Table 2.8-A Mapping JVM instructions to IEEE 754 operations

JVM Instruction Corresponding IEEE 754 Operation
dadd (6.5.dadd), fadd (6.5.fadd) addition
dsub (6.5.dsub), fsub (6.5.fsub) subtraction
dmul (6.5.dmul), fsub (6.5.fmul) multiplication
ddiv (6.5.ddiv), fdiv (6.5.fdiv) division
dneg (6.5.dneg), fneg (6.5.fneg) negate
i2d (6.5.i2d), i2f (6.5.i2f), l2d (6.5.l2d), l2f (6.5.l2f) convertFromInt
d2i (6.5.d2i), d2l (6.5.d2l), f2i (6.5.f2i), f2l (6.5.f2l) convertToIntegerTowardZero
d2f (6.5.d2f), f2d (6.5.f2d) convertFormat
dcmp<op> (6.5.dcmp_op), fcmp<op> (6.5.fcmp_op) compareQuietEqual, compareQuietNotEqual, compareQuietGreater, compareQuietGreaterEqual, compareQuietLess, compareQuietLessEqual

Discussion of key differences moved up from the old section 2.8.1 and edited.

The key differences between the floating-point arithmetic supported by the Java Virtual Machine and the IEEE 754 Standard are:

Not all operations required by IEEE 754 have corresponding Java Virtual Machine instructions. Some IEEE 754 operations without corresponding Java instructions have methods in the java.lang.Math and java.lang.StrictMath classes including the sqrt method for the squareRoot operation and the fma method for the fusedMultiplyAdd operation.

The floating-point remainder instructions drem (6.5.drem) and frem (6.5.frem) are defined differently than the IEEE 754 remainder. The drem and frem instructions are based on an implied division using the round toward zero rounding policy. The IEEE 754 remainder is instead based on an implied division using the round to nearest rounding policy.

The IEEE 754 remainder operation is provided by the library method Math.IEEEremainder or StrictMath.IEEEremainder.

In particular, the The Java Virtual Machine requires full support of IEEE 754 subnormal floating-point numbers and gradual underflow, which make it easier to prove desirable properties of particular numerical algorithms.

Java 1.0 and 1.1 required strict floating-point expression evaluation. In a strict floating-point expression evaluation policy, each float operand corresponds to a value representable in the IEEE 754 binary32 format, each double operand corresponds to a value representable in the IEEE 754 binary64 format, and each floating-point instruction with a corresponding IEEE 754 operation must match the IEEE 754 result for the same operands.

This model provides predictable results for the evaluation of floating-point expressions. However, there were performance problems when this model was delivered in Java Virtual Machine implementations for some processor families common in the Java 1.0/1.1 era.

In Java 1.2. through Java SE 16, the platform allowed an implementation to have one or two value sets associated with each floating-point type. The float type was associated with the float value set and float-extended-exponent value set. Likewise, the double type was associated with the double value set and double-extended-exponent value set. The float value set corresponded to the values representable in the IEEE 754 binary32 format. The float-extended-exponent value set had the same number of precision bits as the binary32 format, but larger exponent range. The double value set corresponded to the values representable in the IEEE 754 binary64 format. The double-extended-exponent value set had the same number of precision bits as the binary64 format, but larger exponent range. Allowing use of the extended exponent value sets by default ameliorated the performance problems on some processor families.

The ACC_STRICT flag on a method forbade the use of extended exponent value sets. In other words, ACC_STRICT constrained the floating-point semantics of any enclosed expressions to strictly use the float value set for float expressions and the double value set for double expressions, meaning the results of such expressions were fully predictable. Methods modified by ACC_STRICT had equivalent floating-point semantics to those specified in the Java 1.0 and 1.1 platforms.

As of Java SE 17, implementations are once again required to only support the original, strict, floating-point execution model. The concepts of value sets and value set conversion have been removed from the specification. Value sets and value set conversion were threaded throughout the specification, including several dozen instructions in chapter 6. The ACC_STRICT flag no longer has any effect on the semantics of a method since all floating-point arithmetic must be evaluated strictly. Due to design and implementation changes made subsequent to Java 1.2, newer members of the processor families that had performance problems executing strict evaluation no longer have that difficulty.

The bit position used for the method flag ACC_STRICT (4.6) is unassigned for class files with a major version of 61 or greater and may be repurposed for other uses in later major class file versions.

Floating-point arithmetic is an approximation to real arithmetic. While there are an infinite number of real numbers, a particular floating-point format only has a finite number of values. In the Java Virtual Machine, a rounding policy is a function used to map from a real number to a floating-point value in a given format. For real numbers in the representable range of a floating-point format, a continuous segment of the real number line is mapped to a single floating-point value. The real number whose value is numerically equal to a floating-point value is mapped to that floating-point value; for example, the real number 1.5 is mapped to the floating-point value 1.5 in a given format. The Java Virtual Machine defines two rounding policies, as follows:

The Java Virtual Machine requires that floating-point arithmetic behave as if every floating-point instruction rounds its floating-point result to the result precision. The rounding policy used by each instruction is either round to nearest or round toward zero, as specified above.

2.8.1 Java Virtual Machine Floating-Point Arithmetic and IEEE 754 Subsection text folding into parent section

The key differences between the floating-point arithmetic supported by the Java Virtual Machine and the IEEE 754 Standard are:

2.8.2 Floating-Point Modes Subsection text folding into parent section

Every method has a floating-point mode, which is either FP-strict or not FP-strict. The floating-point mode of a method is determined by the setting of the ACC_STRICT flag of the access_flags item of the method_info structure (4.6) defining the method. A method for which this flag is set is FP-strict; otherwise, the method is not FP-strict.

Note that this mapping of the ACC_STRICT flag implies that methods in classes compiled by a compiler in JDK release 1.1 or earlier are effectively not FP-strict.

We will refer to an operand stack as having a given floating-point mode when the method whose invocation created the frame containing the operand stack has that floating-point mode. Similarly, we will refer to a Java Virtual Machine instruction as having a given floating-point mode when the method containing that instruction has that floating-point mode.

If a float-extended-exponent value set is supported (2.3.2), values of type float on an operand stack that is not FP-strict may range over that value set except where prohibited by value set conversion (2.8.3). If a double-extended-exponent value set is supported (2.3.2), values of type double on an operand stack that is not FP-strict may range over that value set except where prohibited by value set conversion.

In all other contexts, whether on the operand stack or elsewhere, and regardless of floating-point mode, floating-point values of type float and double may only range over the float value set and double value set, respectively. In particular, class and instance fields, array elements, local variables, and method parameters may only contain values drawn from the standard value sets.

2.8.3 Value Set Conversion Deleted Subsection

An implementation of the Java Virtual Machine that supports an extended floating-point value set is permitted or required, under specified circumstances, to map a value of the associated floating-point type between the extended and the standard value sets. Such a value set conversion is not a type conversion, but a mapping between the value sets associated with the same type.

Where value set conversion is indicated, an implementation is permitted to perform one of the following operations on a value:

In addition, where value set conversion is indicated, certain operations are required:

Such required value set conversions may occur as a result of passing a parameter of a floating-point type during method invocation, including native method invocation; returning a value of a floating-point type from a method that is not FP-strict to a method that is FP-strict; or storing a value of a floating-point type into a local variable, a field, or an array in a method that is not FP-strict.

Not all values from an extended-exponent value set can be mapped exactly to a value in the corresponding standard value set. If a value being mapped is too large to be represented exactly (its exponent is greater than that permitted by the standard value set), it is converted to a (positive or negative) infinity of the corresponding type. If a value being mapped is too small to be represented exactly (its exponent is smaller than that permitted by the standard value set), it is rounded to the nearest of a representable subnormal value or zero of the same sign.

Value set conversion preserves infinities and NaNs and cannot change the sign of the value being converted. Value set conversion has no effect on a value that is not of a floating-point type.

2.11 Instruction Set Summary

2.11.4 Type Conversion Instructions

The type conversion instructions allow conversion between Java Virtual Machine numeric types. These may be used to implement explicit conversions in user code or to mitigate the lack of orthogonality in the instruction set of the Java Virtual Machine.

The Java Virtual Machine directly supports the following widening numeric conversions:

The widening numeric conversion instructions are i2l, i2f, i2d, l2f, l2d, and f2d. The mnemonics for these opcodes are straightforward given the naming conventions for typed instructions and the punning use of 2 to mean "to." For instance, the i2d instruction converts an int value to a double.

Most widening numeric conversions do not lose information about the overall magnitude of a numeric value. Indeed, conversions widening from int to long and int to double do not lose any information at all; the numeric value is preserved exactly. Conversions widening from float to double that are FP-strict (2.8.2) also preserve the numeric value exactly ; only such conversions that are not FP-strict may lose information about the overall magnitude of the converted value.

Conversions from int to float, or from long to float, or from long to double, may lose precision, that is, may lose some of the least significant bits of the value; the resulting floating-point value is a correctly rounded version of the integer value, using the round to nearest rounding policy (2.8).

Despite the fact that loss of precision may occur, widening numeric conversions never cause the Java Virtual Machine to throw a run-time exception (not to be confused with an IEEE 754 floating-point exception).

A widening numeric conversion of an int to a long simply sign-extends the two's-complement representation of the int value to fill the wider format. A widening numeric conversion of a char to an integral type zero-extends the representation of the char value to fill the wider format.

Note that widening numeric conversions do not exist from integral types byte, char, and short to type int. As noted in 2.11.1, values of type byte, char, and short are internally widened to type int, making these conversions implicit.

The Java Virtual Machine also directly supports the following narrowing numeric conversions:

The narrowing numeric conversion instructions are i2b, i2c, i2s, l2i, f2i, f2l, d2i, d2l, and d2f. A narrowing numeric conversion can result in a value of different sign, a different order of magnitude, or both; it may thereby lose precision.

A narrowing numeric conversion of an int or long to an integral type T simply discards all but the n lowest-order bits, where n is the number of bits used to represent type T. This may cause the resulting value not to have the same sign as the input value.

In a narrowing numeric conversion of a floating-point value to an integral type T, where T is either int or long, the floating-point value is converted as follows:

A narrowing numeric conversion from double to float behaves in accordance with IEEE 754. The result is correctly rounded using the round to nearest rounding policy (2.8). A value too small to be represented as a float is converted to a positive or negative zero of type float; a value too large to be represented as a float is converted to a positive or negative infinity. A double NaN is always converted to a float NaN.

Despite the fact that overflow, underflow, or loss of precision may occur, narrowing conversions among numeric types never cause the Java Virtual Machine to throw a run-time exception (not to be confused with an IEEE 754 floating-point exception).

Chapter 4: The class File Format

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 a method_info structure.

No two methods in one class file may have the same name and descriptor (4.3.3).

The structure has the following format:

method_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

The items of the method_info structure are as follows:

access_flags

The value of the access_flags item is a mask of flags used to denote access permission to and properties of this method. The interpretation of each flag, when set, is specified in Table 4.6-A.

Table 4.6-A. Method access and property flags

Flag Name Value Interpretation
ACC_PUBLIC 0x0001 Declared public; may be accessed from outside its package.
ACC_PRIVATE 0x0002 Declared private; accessible only within the defining class and other classes belonging to the same nest (5.4.4).
ACC_PROTECTED 0x0004 Declared protected; may be accessed within subclasses.
ACC_STATIC 0x0008 Declared static.
ACC_FINAL 0x0010 Declared final; must not be overridden (5.4.5).
ACC_SYNCHRONIZED 0x0020 Declared synchronized; invocation is wrapped by a monitor use.
ACC_BRIDGE 0x0040 A bridge method, generated by the compiler.
ACC_VARARGS 0x0080 Declared with variable number of arguments.
ACC_NATIVE 0x0100 Declared native; implemented in a language other than the Java programming language.
ACC_ABSTRACT 0x0400 Declared abstract; no implementation is provided.
ACC_STRICT 0x0800 Declared strictfp ; floating-point mode is FP-strict if the major version number of the class file is at least 46 and at most 60
ACC_SYNTHETIC 0x1000 Declared synthetic; not present in the source code.

The value 0x0800 is interpreted as the ACC_STRICT flag only in a class file whose major version number is at least 46 and at most 60. For methods in such a class file, the rules of this section determine whether ACC_STRICT may be set in combination with other flags. (The setting of the ACC_STRICT flag constrained the float and double operands and results of a method's floating-point instructions in Java SE 1.2 through 16, inclusive (2.8).) For methods in a class file whose major version number is less than 46 or greater than 60, the value 0x0800 is not interpreted as the ACC_STRICT flag, but rather is unassigned; it is not meaningful to "set" the ACC_STRICT flag for methods in such a class file.

Methods of classes may have any of the flags in Table 4.6-A set. However, each method of a class may have at most one of its ACC_PUBLIC, ACC_PRIVATE, and ACC_PROTECTED flags set (JLS §8.4.3).

Methods of interfaces may have any of the flags in Table 4.6-A set except ACC_PROTECTED, ACC_FINAL, ACC_SYNCHRONIZED, and ACC_NATIVE (JLS §9.4). In a class file whose version number is less than 52.0, each method of an interface must have its ACC_PUBLIC and ACC_ABSTRACT flags set; in a class file whose version number is 52.0 or above, each method of an interface must have exactly one of its ACC_PUBLIC and ACC_PRIVATE flags set.

If a method of a class or interface has its ACC_ABSTRACT flag set, it must not have any of its ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNCHRONIZED, ACC_NATIVE, or ACC_STRICT flags set nor, if the class file's major version number is at least 46 and at most 60, its ACC_STRICT flag set.

An instance initialization method (2.9.1) may have at most one of its ACC_PUBLIC, ACC_PRIVATE, and ACC_PROTECTED flags set, and may also have its ACC_VARARGS, ACC_STRICT (in a class file whose major version number is at least 46 and at most 60), and ACC_SYNTHETIC flags set, but must not have any of the other flags in Table 4.6-A set.

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

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

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

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

The ACC_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 the access_flags item not assigned in Table 4.6-A are reserved for future use. They should be set to zero in generated class files and should be ignored by Java Virtual Machine implementations. This includes the bit corresponding to 0x0800 in a class file whose major version number is less than 46 or greater than 60.

name_index

The value of the name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure (4.4.7) representing either 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 the descriptor_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing a valid method descriptor (4.3.3). 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 a void method.

  • If the name of the method is <clinit>, then the descriptor must denote a void method, and, in a class 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 the ACC_VARARGS flag is set in the access_flags item.

attributes_count

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

attributes[]

Each value of the attributes table must be an attribute_info structure (4.7).

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

The attributes defined by this specification as appearing in the attributes table of a method_info structure are listed in Table 4.7-C.

The rules concerning attributes defined to appear in the attributes table of a method_info structure are given in 4.7.

The rules concerning non-predefined attributes in the attributes table of a method_info structure are given in 4.7.1.

Chapter 6: The Java Virtual Machine Instruction Set

6.5 Instructions

d2f

Operation

Convert double to float

Format

d2f

Forms

d2f = 144 (0x90)

Operand Stack

..., value

..., result

Description

The value on the top of the operand stack must be of type double. It is popped from the operand stack and undergoes value set conversion (2.8.3) resulting in value'. Then value'value is converted to a float result using the round to nearest rounding policy (2.8). The result is pushed onto the operand stack.

Where an d2f instruction is FP-strict (2.8.2), the result of the conversion is always rounded to the nearest representable value in the float value set (2.3.2).

Where an d2f instruction is not FP-strict, the result of the conversion may be taken from the float-extended-exponent value set (2.3.2); it is not necessarily rounded to the nearest representable value in the float value set.

A finite value'value too small to be represented as a float is converted to a zero of the same sign; a finite value'value too large to be represented as a float is converted to an infinity of the same sign. A double NaN is converted to a float NaN.

Notes

The d2f instruction performs a narrowing primitive conversion (JLS §5.1.3). It may lose information about the overall magnitude of value'value and may also lose precision.

d2i

Operation

Convert double to int

Format

d2i

Forms

d2i = 142 (0x8e)

Operand Stack

..., value

..., result

Description

The value on the top of the operand stack must be of type double. It is popped from the operand stack and undergoes value set conversion (2.8.3) resulting in value'. Then value'value is converted to an int result. The result is pushed onto the operand stack:

  • If the value'value is NaN, the result of the conversion is an int 0.

  • Otherwise, if the value'value is not an infinity, it is rounded to an integer value V using the round toward zero rounding policy (2.8). If this integer value V can be represented as an int, then the result is the int value V.

  • Otherwise, either the value'value must be too small (a negative value of large magnitude or negative infinity), and the result is the smallest representable value of type int, or the value'value must be too large (a positive value of large magnitude or positive infinity), and the result is the largest representable value of type int.

Notes

The d2i instruction performs a narrowing primitive conversion (JLS §5.1.3). It may lose information about the overall magnitude of value'value and may also lose precision.

d2l

Operation

Convert double to long

Format

d2l

Forms

d2l = 143 (0x8f)

Operand Stack

..., value

..., result

Description

The value on the top of the operand stack must be of type double. It is popped from the operand stack and undergoes value set conversion (2.8.3) resulting in value'. Then value'value is converted to a long. The result is pushed onto the operand stack:

  • If the value'value is NaN, the result of the conversion is a long 0.

  • Otherwise, if the value'value is not an infinity, it is rounded to an integer value V using the round toward zero rounding policy (2.8). If this integer value V can be represented as a long, then the result is the long value V.

  • Otherwise, either the value'value must be too small (a negative value of large magnitude or negative infinity), and the result is the smallest representable value of type long, or the value'value must be too large (a positive value of large magnitude or positive infinity), and the result is the largest representable value of type long.

Notes

The d2l instruction performs a narrowing primitive conversion (JLS §5.1.3). It may lose information about the overall magnitude of value'value and may also lose precision.

dadd

Operation

Add double

Format

dadd

Forms

dadd = 99 (0x63)

Operand Stack

..., value1, value2

..., result

Description

Both value1 and value2 must be of type double. The values are popped from the operand stack and undergo value set conversion (2.8.3), resulting in value1' and value2'. The double result is value1''value1 + value2'value2. The result is pushed onto the operand stack.

The result of a dadd instruction is governed by the rules of IEEE 754 arithmetic:

  • If either value1''value1 or value2'value2 is NaN, the result is NaN.

  • The sum of two infinities of opposite sign is NaN.

  • The sum of two infinities of the same sign is the infinity of that sign.

  • The sum of an infinity and any finite value is equal to the infinity.

  • The sum of two zeroes of opposite sign is positive zero.

  • The sum of two zeroes of the same sign is the zero of that sign.

  • The sum of a zero and a nonzero finite value is equal to the nonzero value.

  • The sum of two nonzero finite values of the same magnitude and opposite sign is positive zero.

  • In the remaining cases, where neither operand is an infinity, a zero, or NaN and the values have the same sign or have different magnitudes, the sum is computed and rounded to the nearest representable value using the round to nearest rounding policy (2.8). If the magnitude is too large to represent as adouble, we say the operation overflows; the result is then an infinity of appropriate sign. If the magnitude is too small to represent as a double, we say the operation underflows; the result is then a zero of appropriate sign.

The Java Virtual Machine requires support of gradual underflow. Despite the fact that overflow, underflow, or loss of precision may occur, execution of a dadd instruction never throws a run-time exception.

dastore

Operation

Store into double array

Format

dastore

Forms

dastore = 82 (0x52)

Operand Stack

..., arrayref, index, value

...

Description

The arrayref must be of type reference and must refer to an array whose components are of type double. The index must be of type int, and value must be of type double. The arrayref, index, and value are popped from the operand stack. The double value undergoes value set conversion (2.8.3), resulting in value', which is stored as the component of the array indexed by index.

Run-time Exceptions

If arrayref is null, dastore throws a NullPointerException.

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

dcmp<op>

Operation

Compare double

Format

dcmp<op>

Forms

dcmpg = 152 (0x98)

dcmpl = 151 (0x97)

Operand Stack

..., value1, value2

..., result

Description

Both value1 and value2 must be of type double. The values are popped from the operand stack and undergo value set conversion (2.8.3), resulting in value1' and value2'. A floating-point comparison is performed:

  • If value1'value1 is greater than value2'value2, the int value 1 is pushed onto the operand stack.

  • Otherwise, if value1'value1 is equal to value2'value2, the int value 0 is pushed onto the operand stack.

  • Otherwise, if value1'value1 is less than value2'value2, the int value -1 is pushed onto the operand stack.

  • Otherwise, at least one of value1'value1 or value2'value2 is NaN. The dcmpg instruction pushes the int value 1 onto the operand stack and the dcmpl instruction pushes the int value -1 onto the operand stack.

Floating-point comparison is performed in accordance with IEEE 754. All values other than NaN are ordered, with negative infinity less than all finite values and positive infinity greater than all finite values. Positive zero and negative zero are considered equal.

Notes

The dcmpg and dcmpl instructions differ only in their treatment of a comparison involving NaN. NaN is unordered, so any double comparison fails if either or both of its operands are NaN. With both dcmpg and dcmpl available, any double comparison may be compiled to push the same result onto the operand stack whether the comparison fails on non-NaN values or fails because it encountered a NaN. For more information, see 3.5.

ddiv

Operation

Divide double

Format

ddiv

Forms

ddiv = 111 (0x6f)

Operand Stack

..., value1, value2

..., result

Description

Both value1 and value2 must be of type double. The values are popped from the operand stack and undergo value set conversion (2.8.3), resulting in value1' and value2'. The double result is value1'value1 / value2'value2. The result is pushed onto the operand stack.

The result of a ddiv instruction is governed by the rules of IEEE 754 arithmetic:

  • If either value1'value1 or value2'value2 is NaN, the result is NaN.

  • If neither value1'value1 nor value2'value2 is NaN, the sign of the result is positive if both values have the same sign, negative if the values have different signs.

  • Division of an infinity by an infinity results in NaN.

  • Division of an infinity by a finite value results in a signed infinity, with the sign-producing rule just given.

  • Division of a finite value by an infinity results in a signed zero, with the sign-producing rule just given.

  • Division of a zero by a zero results in NaN; division of zero by any other finite value results in a signed zero, with the sign-producing rule just given.

  • Division of a nonzero finite value by a zero results in a signed infinity, with the sign-producing rule just given.

  • In the remaining cases, where neither operand is an infinity, a zero, or NaN, the quotient is computed and rounded to the nearest double using the round to nearest rounding policy (2.8). If the magnitude is too large to represent as a double, we say the operation overflows; the result is then an infinity of appropriate sign. If the magnitude is too small to represent as a double, we say the operation underflows; the result is then a zero of appropriate sign.

The Java Virtual Machine requires support of gradual underflow. Despite the fact that overflow, underflow, division by zero, or loss of precision may occur, execution of a ddiv instruction never throws a run-time exception.

dmul

Operation

Multiply double

Format

dmul

Forms

dmul = 107 (0x6b)

Operand Stack

..., value1, value2

..., result

Description

Both value1 and value2 must be of type double. The values are popped from the operand stack and undergo value set conversion (2.8.3), resulting in value1' and value2'. The double result is value1'value1 * value2'value2. The result is pushed onto the operand stack.

The result of a dmul instruction is governed by the rules of IEEE 754 arithmetic:

  • If either value1'value1 or value2'value2 is NaN, the result is NaN.

  • If neither value1'value1 nor value2'value2 is NaN, the sign of the result is positive if both values have the same sign and negative if the values have different signs.

  • Multiplication of an infinity by a zero results in NaN.

  • Multiplication of an infinity by a finite value results in a signed infinity, with the sign-producing rule just given.

  • In the remaining cases, where neither an infinity nor NaN is involved, the product is computed and rounded to the nearest representable value using the round to nearest rounding policy (2.8). If the magnitude is too large to represent as a double, we say the operation overflows; the result is then an infinity of appropriate sign. If the magnitude is too small to represent as a double, we say the operation underflows; the result is then a zero of appropriate sign.

The Java Virtual Machine requires support of gradual underflow. Despite the fact that overflow, underflow, or loss of precision may occur, execution of a dmul instruction never throws a run-time exception.

dneg

Operation

Negate double

Format

dneg

Forms

dneg = 119 (0x77)

Operand Stack

..., value

..., result

Description

The value must be of type double. It is popped from the operand stack and undergoes value set conversion (2.8.3), resulting in value'. The double result is the arithmetic negation of value'value. The result is pushed onto the operand stack.

For double values, negation is not the same as subtraction from zero. If x is +0.0, then 0.0-x equals +0.0, but -x equals -0.0. Unary minus merely inverts the sign of a double.

Special cases of interest:

  • If the operand is NaN, the result is NaN (recall that NaN has no sign).

    Note that the Java Virtual Machine has not adopted the stronger requirement from the IEEE 754-2019 standard that negation inverts the sign bit for all inputs, including NaN.

  • If the operand is an infinity, the result is the infinity of opposite sign.

  • If the operand is a zero, the result is the zero of opposite sign.

drem

Operation

Remainder double

Format

drem

Forms

drem = 115 (0x73)

Operand Stack

..., value1, value2

..., result

Description

Both value1 and value2 must be of type double. The values are popped from the operand stack and undergo value set conversion (2.8.3), resulting in value1' and value2'. The double result is calculated and pushed onto the operand stack.

The result of a drem instruction is not the same as the result of the remainder operation defined by IEEE 754, due to the choice of rounding policy in the Java Virtual Machine (2.8). The IEEE 754 remainder operation computes the remainder from a rounding division, not a truncating division, and so its behavior is not analogous to that of the usual integer remainder operator. Instead, the Java Virtual Machine defines drem to behave in a manner analogous to that of the integer remainder instructions irem and lrem, with an implied division using the round toward zero rounding policy; this may be compared with the C library function fmod.

The result of a drem instruction is governed by the following rules, which match IEEE 754 arithmetic except for how the implied division is computed:

  • If either value1'value1 or value2'value2 is NaN, the result is NaN.

  • If neither value1'value1 nor value2'value2 is NaN, the sign of the result equals the sign of the dividend.

  • If the dividend is an infinity or the divisor is a zero or both, the result is NaN.

  • If the dividend is finite and the divisor is an infinity, the result equals the dividend.

  • If the dividend is a zero and the divisor is finite, the result equals the dividend.

  • In the remaining cases, where neither operand is an infinity, a zero, or NaN, the floating-point remainder result from a dividend value1'value1 and a divisor value2'value2 is defined by the mathematical relation result = value1'value1 - (value2'value2 * q), where q is an integer that is negative only if value1'value1 / value2'value2 is negative, and positive only if value1'value1 / value2'value2 is positive, and whose magnitude is as large as possible without exceeding the magnitude of the true mathematical quotient of value1'value1 and value2'value2.

Despite the fact that division by zero may occur, evaluation of a drem instruction never throws a run-time exception. Overflow, underflow, or loss of precision cannot occur.

Notes

The IEEE 754 remainder operation may be computed by the library routine Math.IEEEremainder or StrictMath.IEEEremainder.

dreturn

Operation

Return double from method

Format

dreturn

Forms

dreturn = 175 (0xaf)

Operand Stack

..., value

[empty]

Description

The current method must have return type double. The value must be of type double. If the current method is a synchronized method, the monitor entered or reentered on invocation of the method is updated and possibly exited as if by execution of a monitorexit instruction (6.5.monitorexit) in the current thread. If no exception is thrown, value is popped from the operand stack of the current frame (2.6) and undergoes value set conversion (2.8.3), resulting in value'. The value'value is pushed onto the operand stack of the frame of the invoker. Any other values on the operand stack of the current method are discarded.

The interpreter then returns control to the invoker of the method, reinstating the frame of the invoker.

Run-time Exceptions

If the Java Virtual Machine implementation does not enforce the rules on structured locking described in 2.11.10, then if the current method is a synchronized method and the current thread is not the owner of the monitor entered or reentered on invocation of the method, dreturn throws an IllegalMonitorStateException. This can happen, for example, if a synchronized method contains a monitorexit instruction, but no monitorenter instruction, on the object on which the method is synchronized.

Otherwise, if the Java Virtual Machine implementation enforces the rules on structured locking described in 2.11.10 and if the first of those rules is violated during invocation of the current method, then dreturn throws an IllegalMonitorStateException.

dstore

Operation

Store double into local variable

Format

dstore
index

Forms

dstore = 57 (0x39)

Operand Stack

..., value

...

Description

The index is an unsigned byte. Both index and index+1 must be indices into the local variable array of the current frame (2.6). The value on the top of the operand stack must be of type double. It is popped from the operand stack and undergoes value set conversion (2.8.3), resulting in value'. The local variables at index and index+1 are set to value'value.

Notes

The dstore opcode can be used in conjunction with the wide instruction (6.5.wide) to access a local variable using a two-byte unsigned index.

dstore_<n>

Operation

Store double into local variable

Format

dstore_<n>

Forms

dstore_0 = 71 (0x47)

dstore_1 = 72 (0x48)

dstore_2 = 73 (0x49)

dstore_3 = 74 (0x4a)

Operand Stack

..., value

...

Description

Both <n> and <n>+1 must be indices into the local variable array of the current frame (2.6). The value on the top of the operand stack must be of type double. It is popped from the operand stack and undergoes value set conversion (2.8.3), resulting in value'. The local variables at <n> and <n>+1 are set to value'value.

Notes

Each of the dstore_<n> instructions is the same as dstore with an index of <n>, except that the operand <n> is implicit.

dsub

Operation

Subtract double

Format

dsub

Forms

dsub = 103 (0x67)

Operand Stack

..., value1, value2

..., result

Description

Both value1 and value2 must be of type double. The values are popped from the operand stack and undergo value set conversion (2.8.3), resulting in value1' and value2'. The double result is value1'value1 - value2'value2. The result is pushed onto the operand stack.

For double subtraction, it is always the case that a-b produces the same result as a+(-b). However, for the dsub instruction, subtraction from zero is not the same as negation, because if x is +0.0, then 0.0-x equals +0.0, but -x equals -0.0.

The Java Virtual Machine requires support of gradual underflow. Despite the fact that overflow, underflow, or loss of precision may occur, execution of a dsub instruction never throws a run-time exception.

f2d

Operation

Convert float to double

Format

f2d

Forms

f2d = 141 (0x8d)

Operand Stack

..., value

..., result

Description

The value on the top of the operand stack must be of type float. It is popped from the operand stack and undergoes value set conversion (2.8.3), resulting in value'. Then value'value is converted to a double result. This result is pushed onto the operand stack.

Notes

Where an f2d instruction is FP-strict (2.8.2) it performs a widening primitive conversion (JLS §5.1.2). Because all values of the float value set (2.3.2) are exactly representable by values of the double value set (2.3.2), such a conversion is exact.

Where an f2d instruction is not FP-strict, the result of the conversion may be taken from the double-extended-exponent value set; it is not necessarily rounded to the nearest representable value in the double value set. However, if the operand value is taken from the float-extended-exponent value set and the target result is constrained to the double value set, rounding of value may be required.

The f2d instruction performs a widening primitive conversion (JLS §5.1.2).

f2i

Operation

Convert float to int

Format

f2i

Forms

f2i = 139 (0x8b)

Operand Stack

..., value

..., result

Description

The value on the top of the operand stack must be of type float. It is popped from the operand stack and undergoes value set conversion (2.8.3), resulting in value'. Then value'value is converted to an int result. This result is pushed onto the operand stack:

  • If the value'value is NaN, the result of the conversion is an int 0.

  • Otherwise, if the value'value is not an infinity, it is rounded to an integer value V using the round toward zero rounding policy (2.8). If this integer value V can be represented as an int, then the result is the int value V.

  • Otherwise, either the value'value must be too small (a negative value of large magnitude or negative infinity), and the result is the smallest representable value of type int, or the value' must be too large (a positive value of large magnitude or positive infinity), and the result is the largest representable value of type int.

Notes

The f2i instruction performs a narrowing primitive conversion (JLS §5.1.3). It may lose information about the overall magnitude of value'value and may also lose precision.

f2l

Operation

Convert float to long

Format

f2l

Forms

f2l = 140 (0x8c)

Operand Stack

..., value

..., result

Description

The value on the top of the operand stack must be of type float. It is popped from the operand stack and undergoes value set conversion (2.8.3), resulting in value'. Then value'value is converted to a long result. This result is pushed onto the operand stack:

  • If the value'value is NaN, the result of the conversion is a long 0.

  • Otherwise, if the value'value is not an infinity, it is rounded to an integer value V using the round toward zero rounding policy (2.8). If this integer value V can be represented as a long, then the result is the long value V.

  • Otherwise, either the value'value must be too small (a negative value of large magnitude or negative infinity), and the result is the smallest representable value of type long, or the value'value must be too large (a positive value of large magnitude or positive infinity), and the result is the largest representable value of type long.

Notes

The f2l instruction performs a narrowing primitive conversion (JLS §5.1.3). It may lose information about the overall magnitude of value'value and may also lose precision.

fadd

Operation

Add float

Format

fadd

Forms

fadd = 98 (0x62)

Operand Stack

..., value1, value2

..., result

Description

Both value1 and value2 must be of type float. The values are popped from the operand stack and undergo value set conversion (2.8.3), resulting in value1' and value2'. The float result is value1'value1 + value2'value2. The result is pushed onto the operand stack.

The result of an fadd instruction is governed by the rules of IEEE 754 arithmetic:

  • If either value1'value1 or value2'value2 is NaN, the result is NaN.

  • The sum of two infinities of opposite sign is NaN.

  • The sum of two infinities of the same sign is the infinity of that sign.

  • The sum of an infinity and any finite value is equal to the infinity.

  • The sum of two zeroes of opposite sign is positive zero.

  • The sum of two zeroes of the same sign is the zero of that sign.

  • The sum of a zero and a nonzero finite value is equal to the nonzero value.

  • The sum of two nonzero finite values of the same magnitude and opposite sign is positive zero.

  • In the remaining cases, where neither operand is an infinity, a zero, or NaN and the values have the same sign or have different magnitudes, the sum is computed and rounded to the nearest representable value using the round to nearest rounding policy (2.8). If the magnitude is too large to represent as a float, we say the operation overflows; the result is then an infinity of appropriate sign. If the magnitude is too small to represent as a float, we say the operation underflows; the result is then a zero of appropriate sign.

The Java Virtual Machine requires support of gradual underflow. Despite the fact that overflow, underflow, or loss of precision may occur, execution of an fadd instruction never throws a run-time exception.

fastore

Operation

Store into float array

Format

fastore

Forms

fastore = 81 (0x51)

Operand Stack

..., arrayref, index, value

...

Description

The arrayref must be of type reference and must refer to an array whose components are of type float. The index must be of type int, and the value must be of type float. The arrayref, index, and value are popped from the operand stack. The float value undergoes value set conversion (2.8.3), resulting in value', and value' is stored as the component of the array indexed by index.

Run-time Exceptions

If arrayref is null, fastore throws a NullPointerException.

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

fcmp<op>

Operation

Compare float

Format

fcmp<op>

Forms

fcmpg = 150 (0x96)

fcmpl = 149 (0x95)

Operand Stack

..., value1, value2

..., result

Description

Both value1 and value2 must be of type float. The values are popped from the operand stack and undergo value set conversion (2.8.3), resulting in value1' and value2'. A floating-point comparison is performed:

  • If value1'value1 is greater than value2'value2, the int value 1 is pushed onto the operand stack.

  • Otherwise, if value1'value1 is equal to value2'value2, the int value 0 is pushed onto the operand stack.

  • Otherwise, if value1'value1 is less than value2'value2, the int value -1 is pushed onto the operand stack.

  • Otherwise, at least one of value1'value1 or value2'value2 is NaN. The fcmpg instruction pushes the int value 1 onto the operand stack and the fcmpl instruction pushes the int value -1 onto the operand stack.

Floating-point comparison is performed in accordance with IEEE 754. All values other than NaN are ordered, with negative infinity less than all finite values and positive infinity greater than all finite values. Positive zero and negative zero are considered equal.

Notes

The fcmpg and fcmpl instructions differ only in their treatment of a comparison involving NaN. NaN is unordered, so any float comparison fails if either or both of its operands are NaN. With both fcmpg and fcmpl available, any float comparison may be compiled to push the same result onto the operand stack whether the comparison fails on non-NaN values or fails because it encountered a NaN. For more information, see 3.5.

fdiv

Operation

Divide float

Format

fdiv

Forms

fdiv = 110 (0x6e)

Operand Stack

..., value1, value2

..., result

Description

Both value1 and value2 must be of type float. The values are popped from the operand stack and undergo value set conversion (2.8.3), resulting in value1' and value2'. The float result is value1'value1 / value2'value2. The result is pushed onto the operand stack.

The result of an fdiv instruction is governed by the rules of IEEE 754 arithmetic:

  • If either value1'value1 or value2'value2 is NaN, the result is NaN.

  • If neither value1'value1 or value2'value2 is NaN, the sign of the result is positive if both values have the same sign, negative if the values have different signs.

  • Division of an infinity by an infinity results in NaN.

  • Division of an infinity by a finite value results in a signed infinity, with the sign-producing rule just given.

  • Division of a finite value by an infinity results in a signed zero, with the sign-producing rule just given.

  • Division of a zero by a zero results in NaN; division of zero by any other finite value results in a signed zero, with the sign-producing rule just given.

  • Division of a nonzero finite value by a zero results in a signed infinity, with the sign-producing rule just given.

  • In the remaining cases, where neither operand is an infinity, a zero, or NaN, the quotient is computed and rounded to the nearest float using the round to nearest rounding policy (2.8). If the magnitude is too large to represent as a float, we say the operation overflows; the result is then an infinity of appropriate sign. If the magnitude is too small to represent as a float, we say the operation underflows; the result is then a zero of appropriate sign.

The Java Virtual Machine requires support of gradual underflow. Despite the fact that overflow, underflow, division by zero, or loss of precision may occur, execution of an fdiv instruction never throws a run-time exception.

fmul

Operation

Multiply float

Format

fmul

Forms

fmul = 106 (0x6a)

Operand Stack

..., value1, value2

..., result

Description

Both value1 and value2 must be of type float. The values are popped from the operand stack and undergo value set conversion (2.8.3), resulting in value1' and value2'. The float result is value1'value1 * value2'value2. The result is pushed onto the operand stack.

The result of an fmul instruction is governed by the rules of IEEE 754 arithmetic:

  • If either value1'value1 or value2'value2 is NaN, the result is NaN.

  • If neither value1'value1 nor value2'value2 is NaN, the sign of the result is positive if both values have the same sign, and negative if the values have different signs.

  • Multiplication of an infinity by a zero results in NaN.

  • Multiplication of an infinity by a finite value results in a signed infinity, with the sign-producing rule just given.

  • In the remaining cases, where neither an infinity nor NaN is involved, the product is computed and rounded to the nearest representable value using the round to nearest rounding policy (2.8). If the magnitude is too large to represent as a float, we say the operation overflows; the result is then an infinity of appropriate sign. If the magnitude is too small to represent as a float, we say the operation underflows; the result is then a zero of appropriate sign.

The Java Virtual Machine requires support of gradual underflow. Despite the fact that overflow, underflow, or loss of precision may occur, execution of an fmul instruction never throws a run-time exception.

fneg

Operation

Negate float

Format

fneg

Forms

fneg = 118 (0x76)

Operand Stack

..., value

..., result

Description

The value must be of type float. It is popped from the operand stack and undergoes value set conversion (2.8.3), resulting in value'. The float result is the arithmetic negation of value'value. This result is pushed onto the operand stack.

For float values, negation is not the same as subtraction from zero. If x is +0.0, then 0.0-x equals +0.0, but -x equals -0.0. Unary minus merely inverts the sign of a float.

Special cases of interest:

  • If the operand is NaN, the result is NaN (recall that NaN has no sign).

    Note that the Java Virtual Machine has not adopted the stronger requirement from the IEEE 754-2019 standard that negation inverts the sign bit for all inputs, including NaN.

  • If the operand is an infinity, the result is the infinity of opposite sign.

  • If the operand is a zero, the result is the zero of opposite sign.

frem

Operation

Remainder float

Format

frem

Forms

frem = 114 (0x72)

Operand Stack

..., value1, value2

..., result

Description

Both value1 and value2 must be of type float. The values are popped from the operand stack and undergo value set conversion (2.8.3), resulting in value1' and value2'. The float result is calculated and pushed onto the operand stack.

The result of an frem instruction is not the same as the result of the remainder operation defined by IEEE 754, due to the choice of rounding policy in the Java Virtual Machine (2.8). The IEEE 754 remainder operation computes the remainder from a rounding division, not a truncating division, and so its behavior is not analogous to that of the usual integer remainder operator. Instead, the Java Virtual Machine defines frem to behave in a manner analogous to that of the integer remainder instructions irem and lrem, with an implied division using the round toward zero rounding policy; this may be compared with the C library function fmod.

The result of an frem instruction is governed by the following rules, which match IEEE 754 arithmetic except for how the implied division is computed:

  • If either value1'value1 or value2'value2 is NaN, the result is NaN.

  • If neither value1'value1 nor value2'value2 is NaN, the sign of the result equals the sign of the dividend.

  • If the dividend is an infinity or the divisor is a zero or both, the result is NaN.

  • If the dividend is finite and the divisor is an infinity, the result equals the dividend.

  • If the dividend is a zero and the divisor is finite, the result equals the dividend.

  • In the remaining cases, where neither operand is an infinity, a zero, or NaN, the floating-point remainder result from a dividend value1'value1 and a divisor value2'value2 is defined by the mathematical relation result = value1'value1 - (value2'value2 * q), where q is an integer that is negative only if value1'value1 / value2'value2 is negative and positive only if value1'value1 / value2'value2 is positive, and whose magnitude is as large as possible without exceeding the magnitude of the true mathematical quotient of value1'value1 and value2'value2.

Despite the fact that division by zero may occur, evaluation of an frem instruction never throws a run-time exception. Overflow, underflow, or loss of precision cannot occur.

Notes

The IEEE 754 remainder operation may be computed by the library routine Math.IEEEremainder or StrictMath.IEEEremainder.

freturn

Operation

Return float from method

Format

freturn

Forms

freturn = 174 (0xae)

Operand Stack

..., value

[empty]

Description

The current method must have return type float. The value must be of type float. If the current method is a synchronized method, the monitor entered or reentered on invocation of the method is updated and possibly exited as if by execution of a monitorexit instruction (6.5.monitorexit) in the current thread. If no exception is thrown, value is popped from the operand stack of the current frame (2.6) and undergoes value set conversion (2.8.3), resulting in value'. The value'value is pushed onto the operand stack of the frame of the invoker. Any other values on the operand stack of the current method are discarded.

The interpreter then returns control to the invoker of the method, reinstating the frame of the invoker.

Run-time Exceptions

If the Java Virtual Machine implementation does not enforce the rules on structured locking described in 2.11.10, then if the current method is a synchronized method and the current thread is not the owner of the monitor entered or reentered on invocation of the method, freturn throws an IllegalMonitorStateException. This can happen, for example, if a synchronized method contains a monitorexit instruction, but no monitorenter instruction, on the object on which the method is synchronized.

Otherwise, if the Java Virtual Machine implementation enforces the rules on structured locking described in 2.11.10 and if the first of those rules is violated during invocation of the current method, then freturn throws an IllegalMonitorStateException.

fstore

Operation

Store float into local variable

Format

fstore
index

Forms

fstore = 56 (0x38)

Operand Stack

..., value

...

Description

The index is an unsigned byte that must be an index into the local variable array of the current frame (2.6). The value on the top of the operand stack must be of type float. It is popped from the operand stack and undergoes value set conversion (2.8.3), resulting in value'. The value of the local variable at index is set to value'value.

Notes

The fstore opcode can be used in conjunction with the wide instruction (6.5.wide) to access a local variable using a two-byte unsigned index.

fstore_<n>

Operation

Store float into local variable

Format

fstore_<n>

Forms

fstore_0 = 67 (0x43)

fstore_1 = 68 (0x44)

fstore_2 = 69 (0x45)

fstore_3 = 70 (0x46)

Operand Stack

..., value

...

Description

The <n> must be an index into the local variable array of the current frame (2.6). The value on the top of the operand stack must be of type float. It is popped from the operand stack and undergoes value set conversion (2.8.3), resulting in value'. The value of the local variable at <n> is set to value'value.

Notes

Each of the fstore_<n> instructions is the same as fstore with an index of <n>, except that the operand <n> is implicit.

fsub

Operation

Subtract float

Format

fsub

Forms

fsub = 102 (0x66)

Operand Stack

..., value1, value2

..., result

Description

Both value1 and value2 must be of type float. The values are popped from the operand stack and undergo value set conversion (2.8.3), resulting in value1' and value2'. The float result is value1'value1 - value2'value2. The result is pushed onto the operand stack.

For float subtraction, it is always the case that a-b produces the same result as a+(-b). However, for the fsub instruction, subtraction from zero is not the same as negation, because if x is +0.0, then 0.0-x equals +0.0, but -x equals -0.0.

The Java Virtual Machine requires support of gradual underflow. Despite the fact that overflow, underflow, or loss of precision may occur, execution of an fsub instruction never throws a run-time exception.

invokedynamic

The invokedynamic instruction does not mention value set conversion and thus does not need to be updated for JEP 306.

invokeinterface

Operation

Invoke interface method

Format

invokeinterface
indexbyte1
indexbyte2
count
0

Forms

invokeinterface = 185 (0xb9)

Operand Stack

..., objectref, [arg1, [arg2 ...]]

...

Description

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

The resolved interface method must not be an instance initialization method, or the class or interface initialization method (2.9.1, 2.9.2).

The count operand is an unsigned byte that must not be zero. The objectref must be of type reference and must be followed on the operand stack by nargs argument values, where the number, type, and order of the values must be consistent with the descriptor of the resolved interface method. The value of the fourth operand byte must always be zero.

Let C be the class of objectref. A method is selected with respect to C and the resolved method ([5.4.6]). This is the method to be invoked.

If the method to be invoked is synchronized, the monitor associated with objectref is entered or reentered as if by execution of a monitorenter instruction ([6.5.monitorenter]) in the current thread.

If the method to be invoked is not native, the nargs argument values and objectref are popped from the operand stack. A new frame is created on the Java Virtual Machine stack for the method being invoked. The objectref and the argument values are consecutively made the values of local variables of the new frame, with objectref in local variable 0, arg1 in local variable 1 (or, if arg1 is of type long or double, in local variables 1 and 2), and so on. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being stored in a local variable. The new frame is then made current, and the Java Virtual Machine pc is set to the opcode of the first instruction of the method to be invoked. Execution continues with the first instruction of the method.

If the method to be invoked is native and the platform-dependent code that implements it has not yet been bound ([5.6]) into the Java Virtual Machine, then that is done. The nargs argument values and objectref are popped from the operand stack and are passed as parameters to the code that implements the method. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being passed as a parameter. The parameters are passed and the code is invoked in an implementation-dependent manner. When the platform-dependent code returns:

  • If the native method is synchronized, the monitor associated with objectref is updated and possibly exited as if by execution of a monitorexit instruction (6.5.monitorexit) in the current thread.

  • If the native method returns a value, the return value of the platform-dependent code is converted in an implementation-dependent way to the return type of the native method and pushed onto the operand stack.

Linking Exceptions

During resolution of the symbolic reference to the interface method, any of the exceptions pertaining to interface method resolution ([5.4.3.4]) can be thrown.

Otherwise, if the resolved method is static, the invokeinterface instruction throws an IncompatibleClassChangeError.

Note that invokeinterface may refer to private methods declared in interfaces, including nestmate interfaces.

Run-time Exceptions

Otherwise, if objectref is null, the invokeinterface instruction throws a NullPointerException.

Otherwise, if the class of objectref does not implement the resolved interface, invokeinterface throws an IncompatibleClassChangeError.

Otherwise, if the selected method is neither public nor private, invokeinterface throws an IllegalAccessError.

Otherwise, if the selected method is abstract, invokeinterface throws an AbstractMethodError.

Otherwise, if the selected method is native and the code that implements the method cannot be bound, invokeinterface throws an UnsatisfiedLinkError.

Otherwise, if no method is selected, and there are multiple maximally-specific superinterface methods of C that match the resolved method's name and descriptor and are not abstract, invokeinterface throws an IncompatibleClassChangeError

Otherwise, if no method is selected, and there are no maximally-specific superinterface methods of C that match the resolved method's name and descriptor and are not abstract, invokeinterface throws an AbstractMethodError.

Notes

The count operand of the invokeinterface instruction records a measure of the number of argument values, where an argument value of type long or type double contributes two units to the count value and an argument of any other type contributes one unit. This information can also be derived from the descriptor of the selected method. The redundancy is historical.

The fourth operand byte exists to reserve space for an additional operand used in certain of Oracle's Java Virtual Machine implementations, which replace the invokeinterface instruction by a specialized pseudo-instruction at run time. It must be retained for backwards compatibility.

The nargs argument values and objectref are not one-to-one with the first nargs+1 local variables. Argument values of types long and double must be stored in two consecutive local variables, thus more than nargs local variables may be required to pass nargs argument values to the invoked method.

The selection logic allows a non-abstract method declared in a superinterface to be selected. Methods in interfaces are only considered if there is no matching method in the class hierarchy. In the event that there are two non-abstract methods in the superinterface hierarchy, with neither more specific than the other, an error occurs; there is no attempt to disambiguate (for example, one may be the referenced method and one may be unrelated, but we do not prefer the referenced method). On the other hand, if there are many abstract methods but only one non-abstract method, the non-abstract method is selected (unless an abstract method is more specific).

invokespecial

Operation

Invoke instance method; direct invocation of instance initialization methods and methods of the current class and its supertypes

Format

invokespecial
indexbyte1
indexbyte2

Forms

invokespecial = 183 (0xb7)

Operand Stack

..., objectref, [arg1, [arg2 ...]]

...

Description

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

If all of the following are true, let C be the direct superclass of the current class:

  • The resolved method is not an instance initialization method (2.9.1).

  • The symbolic reference names a class (not an interface), and that class is a superclass of the current class.

  • The ACC_SUPER flag is set for the class file ([4.1]).

Otherwise, let C be the class or interface named by the symbolic reference.

The actual method to be invoked is selected by the following lookup procedure:

  1. If C contains a declaration for an instance method with the same name and descriptor as the resolved method, then it is the method to be invoked.

  2. Otherwise, if C is a class and has a superclass, a search for a declaration of an instance method with the same name and descriptor as the resolved method is performed, starting with the direct superclass of C and continuing with the direct superclass of that class, and so forth, until a match is found or no further superclasses exist. If a match is found, then it is the method to be invoked.

  3. Otherwise, if C is an interface and the class Object contains a declaration of a public instance method with the same name and descriptor as the resolved method, then it is the method to be invoked.

  4. Otherwise, if there is exactly one maximally-specific method ([5.4.3.3]) in the superinterfaces of C that matches the resolved method's name and descriptor and is not abstract, then it is the method to be invoked.

The objectref must be of type reference and must be followed on the operand stack by nargs argument values, where the number, type, and order of the values must be consistent with the descriptor of the selected instance method.

If the method is synchronized, the monitor associated with objectref is entered or reentered as if by execution of a monitorenter instruction ([6.5.monitorenter]) in the current thread.

If the method is not native, the nargs argument values and objectref are popped from the operand stack. A new frame is created on the Java Virtual Machine stack for the method being invoked. The objectref and the argument values are consecutively made the values of local variables of the new frame, with objectref in local variable 0, arg1 in local variable 1 (or, if arg1 is of type long or double, in local variables 1 and 2), and so on. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being stored in a local variable. The new frame is then made current, and the Java Virtual Machine pc is set to the opcode of the first instruction of the method to be invoked. Execution continues with the first instruction of the method.

If the method is native and the platform-dependent code that implements it has not yet been bound ([5.6]) into the Java Virtual Machine, that is done. The nargs argument values and objectref are popped from the operand stack and are passed as parameters to the code that implements the method. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being passed as a parameter. The parameters are passed and the code is invoked in an implementation-dependent manner. When the platform-dependent code returns, the following take place:

  • If the native method is synchronized, the monitor associated with objectref is updated and possibly exited as if by execution of a monitorexit instruction (6.5.monitorexit) in the current thread.

  • If the native method returns a value, the return value of the platform-dependent code is converted in an implementation-dependent way to the return type of the native method and pushed onto the operand stack.

Linking Exceptions

During resolution of the symbolic reference to the method, any of the exceptions pertaining to method resolution ([5.4.3.3]) can be thrown.

Otherwise, if the resolved method is an instance initialization method, and the class in which it is declared is not the class symbolically referenced by the instruction, a NoSuchMethodError is thrown.

Otherwise, if the resolved method is a class (static) method, the invokespecial instruction throws an IncompatibleClassChangeError.

Run-time Exceptions

Otherwise, if objectref is null, the invokespecial instruction throws a NullPointerException.

Otherwise, if step 1, step 2, or step 3 of the lookup procedure selects an abstract method, invokespecial throws an AbstractMethodError.

Otherwise, if step 1, step 2, or step 3 of the lookup procedure selects a native method and the code that implements the method cannot be bound, invokespecial throws an UnsatisfiedLinkError.

Otherwise, if step 4 of the lookup procedure determines there are multiple maximally-specific superinterface methods of C that match the resolved method's name and descriptor and are not abstract, invokespecial throws an IncompatibleClassChangeError

Otherwise, if step 4 of the lookup procedure determines there are no maximally-specific superinterface methods of C that match the resolved method's name and descriptor and are not abstract, invokespecial throws an AbstractMethodError.

Notes

The difference between the invokespecial instruction and the invokevirtual instruction ([6.5.invokevirtual]) is that invokevirtual invokes a method based on the class of the object. The invokespecial instruction is used to directly invoke instance initialization methods (2.9.1) as well as methods of the current class and its supertypes.

The invokespecial instruction was named invokenonvirtual prior to JDK release 1.0.2.

The nargs argument values and objectref are not one-to-one with the first nargs+1 local variables. Argument values of types long and double must be stored in two consecutive local variables, thus more than nargs local variables may be required to pass nargs argument values to the invoked method.

The invokespecial instruction handles invocation of a non-abstract interface method, referenced either via a direct superinterface or via a superclass. In these cases, the rules for selection are essentially the same as those for invokeinterface (except that the search starts from a different class).

invokestatic

Operation

Invoke a class (static) method

Format

invokestatic
indexbyte1
indexbyte2

Forms

invokestatic = 184 (0xb8)

Operand Stack

..., [arg1, [arg2 ...]]

...

Description

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

The resolved method must not be an instance initialization method, or the class or interface initialization method (2.9.1, 2.9.2).

The resolved method must be static, and therefore cannot be abstract.

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

The operand stack must contain nargs argument values, where the number, type, and order of the values must be consistent with the descriptor of the resolved method.

If the method is synchronized, the monitor associated with the resolved Class object is entered or reentered as if by execution of a monitorenter instruction ([6.5.monitorenter]) in the current thread.

If the method is not native, the nargs argument values are popped from the operand stack. A new frame is created on the Java Virtual Machine stack for the method being invoked. The nargs argument values are consecutively made the values of local variables of the new frame, with arg1 in local variable 0 (or, if arg1 is of type long or double, in local variables 0 and 1) and so on. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being stored in a local variable. The new frame is then made current, and the Java Virtual Machine pc is set to the opcode of the first instruction of the method to be invoked. Execution continues with the first instruction of the method.

If the method is native and the platform-dependent code that implements it has not yet been bound ([5.6]) into the Java Virtual Machine, that is done. The nargs argument values are popped from the operand stack and are passed as parameters to the code that implements the method. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being passed as a parameter. The parameters are passed and the code is invoked in an implementation-dependent manner. When the platform-dependent code returns, the following take place:

  • If the native method is synchronized, the monitor associated with the resolved Class object is updated and possibly exited as if by execution of a monitorexit instruction (6.5.monitorexit) in the current thread.

  • If the native method returns a value, the return value of the platform-dependent code is converted in an implementation-dependent way to the return type of the native method and pushed onto the operand stack.

Linking Exceptions

During resolution of the symbolic reference to the method, any of the exceptions pertaining to method resolution ([5.4.3.3]) can be thrown.

Otherwise, if the resolved method is an instance method, the invokestatic instruction throws an IncompatibleClassChangeError.

Run-time Exceptions

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

Otherwise, if the resolved method is native and the code that implements the method cannot be bound, invokestatic throws an UnsatisfiedLinkError.

Notes

The nargs argument values are not one-to-one with the first nargs local variables. Argument values of types long and double must be stored in two consecutive local variables, thus more than nargs local variables may be required to pass nargs argument values to the invoked method.

invokevirtual

Operation

Invoke instance method; dispatch based on class

Format

invokevirtual
indexbyte1
indexbyte2

Forms

invokevirtual = 182 (0xb6)

Operand Stack

..., objectref, [arg1, [arg2 ...]]

...

Description

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

If the resolved method is not signature polymorphic ([2.9.3]), then the invokevirtual instruction proceeds as follows.

Let C be the class of objectref. A method is selected with respect to C and the resolved method ([5.4.6]). This is the method to be invoked.

The objectref must be followed on the operand stack by nargs argument values, where the number, type, and order of the values must be consistent with the descriptor of the selected instance method.

If the method to be invoked is synchronized, the monitor associated with objectref is entered or reentered as if by execution of a monitorenter instruction ([6.5.monitorenter]) in the current thread.

If the method to be invoked is not native, the nargs argument values and objectref are popped from the operand stack. A new frame is created on the Java Virtual Machine stack for the method being invoked. The objectref and the argument values are consecutively made the values of local variables of the new frame, with objectref in local variable 0, arg1 in local variable 1 (or, if arg1 is of type long or double, in local variables 1 and 2), and so on. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being stored in a local variable. The new frame is then made current, and the Java Virtual Machine pc is set to the opcode of the first instruction of the method to be invoked. Execution continues with the first instruction of the method.

If the method to be invoked is native and the platform-dependent code that implements it has not yet been bound ([5.6]) into the Java Virtual Machine, that is done. The nargs argument values and objectref are popped from the operand stack and are passed as parameters to the code that implements the method. Any argument value that is of a floating-point type undergoes value set conversion (2.8.3) prior to being passed as a parameter. The parameters are passed and the code is invoked in an implementation-dependent manner. When the platform-dependent code returns, the following take place:

  • If the native method is synchronized, the monitor associated with objectref is updated and possibly exited as if by execution of a monitorexit instruction (6.5.monitorexit) in the current thread.

  • If the native method returns a value, the return value of the platform-dependent code is converted in an implementation-dependent way to the return type of the native method and pushed onto the operand stack.

If the resolved method is signature polymorphic ([2.9.3]), and declared in the java.lang.invoke.MethodHandle class, then the invokevirtual instruction proceeds as follows, where D is the descriptor of the method symbolically referenced by the instruction.

First, a reference to an instance of java.lang.invoke.MethodType is obtained as if by resolution of a symbolic reference to a method type (5.4.3.5) with the same parameter and return types as D.

  • If the named method is invokeExact, the instance of java.lang.invoke.MethodType must be semantically equal to the type descriptor of the receiving method handle objectref. The method handle to be invoked is objectref.

  • If the named method is invoke, and the instance of java.lang.invoke.MethodType is semantically equal to the type descriptor of the receiving method handle objectref, then the method handle to be invoked is objectref.

  • If the named method is invoke, and the instance of java.lang.invoke.MethodType is not semantically equal to the type descriptor of the receiving method handle objectref, then the Java Virtual Machine attempts to adjust the type descriptor of the receiving method handle, as if by invocation of the asType method of java.lang.invoke.MethodHandle, to obtain an exactly invokable method handle m. The method handle to be invoked is m.

The objectref must be followed on the operand stack by nargs argument values, where the number, type, and order of the values must be consistent with the type descriptor of the method handle to be invoked. (This type descriptor will correspond to the method descriptor appropriate for the kind of the method handle to be invoked, as specified in 5.4.3.5.)

Then, if the method handle to be invoked has bytecode behavior, the Java Virtual Machine invokes the method handle as if by execution of the bytecode behavior associated with the method handle's kind. If the kind is 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial), 8 (REF_newInvokeSpecial), or 9 (REF_invokeInterface), then a frame will be created and made current in the course of executing the bytecode behavior; however, this frame is not visible, and when the method invoked by the bytecode behavior completes (normally or abruptly), the frame of its invoker is considered to be the frame for the method containing this invokevirtual instruction.

Otherwise, if the method handle to be invoked has no bytecode behavior, the Java Virtual Machine invokes it in an implementation-dependent manner.

If the resolved method is signature polymorphic and declared in the java.lang.invoke.VarHandle class, then the invokevirtual instruction proceeds as follows, where N and D are the name and descriptor of the method symbolically referenced by the instruction.

First, a reference to an instance of java.lang.invoke.VarHandle.AccessMode is obtained as if by invocation of the valueFromMethodName method of java.lang.invoke.VarHandle.AccessMode with a String argument denoting N.

Second, a reference to an instance of java.lang.invoke.MethodType is obtained as if by invocation of the accessModeType method of java.lang.invoke.VarHandle on the instance objectref, with the instance of java.lang.invoke.VarHandle.AccessMode as the argument.

Third, a reference to an instance of java.lang.invoke.MethodHandle is obtained as if by invocation of the varHandleExactInvoker method of java.lang.invoke.MethodHandles with the instance of java.lang.invoke.VarHandle.AccessMode as the first argument and the instance of java.lang.invoke.MethodType as the second argument. The resulting instance is called the invoker method handle.

Finally, the nargs argument values and objectref are popped from the operand stack, and the invoker method handle is invoked. The invocation occurs as if by execution of an invokevirtual instruction that indicates a run-time constant pool index to a symbolic reference R where:

  • R is a symbolic reference to a method of a class;

  • for the symbolic reference to the class in which the method is to be found, R specifies java.lang.invoke.MethodHandle;

  • for the name of the method, R specifies invoke;

  • for the descriptor of the method, R specifies a return type indicated by the return descriptor of D, and specifies a first parameter type of java.lang.invoke.VarHandle followed by the parameter types indicated by the parameter descriptors of D (if any) in order.

and where it is as if the following items were pushed, in order, onto the operand stack:

  • a reference to the instance of java.lang.invoke.MethodHandle (the invoker method handle);

  • objectref;

  • the nargs argument values, where the number, type, and order of the values must be consistent with the type descriptor of the invoker method handle.

Linking Exceptions

During resolution of the symbolic reference to the method, any of the exceptions pertaining to method resolution ([5.4.3.3]) can be thrown.

Otherwise, if the resolved method is a class (static) method, the invokevirtual instruction throws an IncompatibleClassChangeError.

Otherwise, if the resolved method is signature polymorphic and declared in the java.lang.invoke.MethodHandle class, then during resolution of the method type derived from the descriptor in the symbolic reference to the method, any of the exceptions pertaining to method type resolution (5.4.3.5) can be thrown.

Otherwise, if the resolved method is signature polymorphic and declared in the java.lang.invoke.VarHandle class, then any linking exception that may arise from invocation of the invoker method handle can be thrown. No linking exceptions are thrown from invocation of the valueFromMethodName, accessModeType, and varHandleExactInvoker methods.

Run-time Exceptions

Otherwise, if objectref is null, the invokevirtual instruction throws a NullPointerException.

Otherwise, if the resolved method is not signature polymorphic:

  • If the selected method is abstract, invokevirtual throws an AbstractMethodError.

  • Otherwise, if the selected method is native and the code that implements the method cannot be bound, invokevirtual throws an UnsatisfiedLinkError.

  • Otherwise, if no method is selected, and there are multiple maximally-specific superinterface methods of C that match the resolved method's name and descriptor and are not abstract, invokevirtual throws an IncompatibleClassChangeError

  • Otherwise, if no method is selected, and there are no maximally-specific superinterface methods of C that match the resolved method's name and descriptor and are not abstract, invokevirtual throws an AbstractMethodError.

Otherwise, if the resolved method is signature polymorphic and declared in the java.lang.invoke.MethodHandle class, then:

  • If the method name is invokeExact, and the obtained instance of java.lang.invoke.MethodType is not semantically equal to the type descriptor of the receiving method handle objectref, the invokevirtual instruction throws a java.lang.invoke.WrongMethodTypeException.

  • If the method name is invoke, and the obtained instance of java.lang.invoke.MethodType is not a valid argument to the asType method of java.lang.invoke.MethodHandle invoked on the receiving method handle objectref, the invokevirtual instruction throws a java.lang.invoke.WrongMethodTypeException.

Otherwise, if the resolved method is signature polymorphic and declared in the java.lang.invoke.VarHandle class, then any run-time exception that may arise from invocation of the invoker method handle can be thrown. No run-time exceptions are thrown from invocation of the valueFromMethodName, accessModeType, and varHandleExactInvoker methods, except NullPointerException if objectref is null.

Notes

The nargs argument values and objectref are not one-to-one with the first nargs+1 local variables. Argument values of types long and double must be stored in two consecutive local variables, thus more than nargs local variables may be required to pass nargs argument values to the invoked method.

It is possible that the symbolic reference of an invokevirtual instruction resolves to an interface method. In this case, it is possible that there is no overriding method in the class hierarchy, but that a non-abstract interface method matches the resolved method's descriptor. The selection logic matches such a method, using the same rules as for invokeinterface.

ldc

Operation

Push item from run-time constant pool

Format

ldc
index

Forms

ldc = 18 (0x12)

Operand Stack

...

..., value

Description

The index is an unsigned byte that must be a valid index into the run-time constant pool of the current class (2.5.5). The run-time constant pool entry at index must be loadable (5.1), and not any of the following:

  • A numeric constant of type long or double.

  • A symbolic reference to a dynamically-computed constant whose field descriptor is J (denoting long) or D (denoting double).

If the run-time constant pool entry is a numeric constant of type int or float, then the value of that numeric constant is pushed onto the operand stack as an int or float, respectively.

Otherwise, if the run-time constant pool entry is a string constant, that is, a reference to an instance of class String, then value, a reference to that instance, is pushed onto the operand stack.

Otherwise, if the run-time constant pool entry is a symbolic reference to a class or interface, then the named class or interface is resolved (5.4.3.1) and value, a reference to the Class object representing that class or interface, is pushed onto the operand stack.

Otherwise, the run-time constant pool entry is a symbolic reference to a method type, a method handle, or a dynamically-computed constant. The symbolic reference is resolved (5.4.3.5, 5.4.3.6) and value, the result of resolution, is pushed onto the operand stack.

Linking Exceptions

During resolution of a symbolic reference, any of the exceptions pertaining to resolution of that kind of symbolic reference can be thrown.

Notes

The ldc instruction can only be used to push a value of type float taken from the float value set (2.3.2) because a constant of type float in the constant pool (4.4.4) must be taken from the float value set.

ldc_w

Operation

Push item from run-time constant pool (wide index)

Format

ldc_w
indexbyte1
indexbyte2

Forms

ldc_w = 19 (0x13)

Operand Stack

...

..., value

Description

The unsigned indexbyte1 and indexbyte2 are assembled into an unsigned 16-bit index into the run-time constant pool of the current class (2.5.5), where the value of the index is calculated as (indexbyte1 << 8) | indexbyte2. The index must be a valid index into the run-time constant pool of the current class. The run-time constant pool entry at the index must be loadable (5.1), and not any of the following:

  • A numeric constant of type long or double.

  • A symbolic reference to a dynamically-computed constant whose field descriptor is J (denoting long) or D (denoting double).

If the run-time constant pool entry is a numeric constant of type int or float, or a string constant, then value is determined and pushed onto the operand stack according to the rules given for the ldc instruction.

Otherwise, the run-time constant pool entry is a symbolic reference to a class, interface, method type, method handle, or dynamically-computed constant. It is resolved and value is determined and pushed onto the operand stack according to the rules given for the ldc instruction.

Linking Exceptions

During resolution of a symbolic reference, any of the exceptions pertaining to resolution of that kind of symbolic reference can be thrown.

Notes

The ldc_w instruction is identical to the ldc instruction (6.5.ldc) except for its wider run-time constant pool index.

The ldc_w instruction can only be used to push a value of type float taken from the float value set (2.3.2) because a constant of type float in the constant pool (4.4.4) must be taken from the float value set.

ldc2_w

Operation

Push long or double from run-time constant pool (wide index)

Format

ldc2_w
indexbyte1
indexbyte2

Forms

ldc2_w = 20 (0x14)

Operand Stack

...

..., value

Description

The unsigned indexbyte1 and indexbyte2 are assembled into an unsigned 16-bit index into the run-time constant pool of the current class (2.5.5), where the value of the index is calculated as (indexbyte1 << 8) | indexbyte2. The index must be a valid index into the run-time constant pool of the current class. The run-time constant pool entry at the index must be loadable (5.1), and in particular one of the following:

  • A numeric constant of type long or double.

  • A symbolic reference to a dynamically-computed constant whose field descriptor is J (denoting long) or D (denoting double).

If the run-time constant pool entry is a numeric constant of type long or double, then the value of that numeric constant is pushed onto the operand stack as a long or double, respectively.

Otherwise, the run-time constant pool entry is a symbolic reference to a dynamically-computed constant. The symbolic reference is resolved (5.4.3.6) and value, the result of resolution, is pushed onto the operand stack.

Linking Exceptions

During resolution of a symbolic reference to a dynamically-computed constant, any of the exceptions pertaining to dynamically-computed constant resolution can be thrown.

Notes

Only a wide-index version of the ldc2_w instruction exists; there is no ldc2 instruction that pushes a long or double with a single-byte index.

The ldc2_w instruction can only be used to push a value of type double taken from the double value set (2.3.2) because a constant of type double in the constant pool (4.4.5) must be taken from the double value set.

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 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 of a type that is assignment compatible (JLS §5.2) with 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'.

Otherwise, 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, 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 or interface 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 of a type that is assignment compatible (JLS §5.2) with 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'.

Otherwise, 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.

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).