-
CSR
-
Resolution: Approved
-
P4
-
None
-
behavioral
-
minimal
-
No behavioral change.
-
Java API
-
SE
Summary
Fix the self-contradictory specification in java.lang.invoke.ConstantBoostraps::explicitCast
when value
is null and dstType
is primitive, and correct about conversions to other primitives when value
is Boolean
.
Problem
Parts of the specification of explicitCast
, including one paragraph and the @throws
clause, indicate ClassCastException
is thrown for a null value
and a primitive (non-void) dstType
. This is contradictory to the "The result is the same as when using the following code" block below and the actual behavior, which returns the zero value of the primitive type instead.
In addition, the specification implies Boolean
cannot convert to int
or other primitives (excluding void, same elsewhere in this paragraph) because there is no Java primitive conversions from boolean
to other primitives. However, it is treated as if it's int
with value 1 or 0 for true/false. We need to clarify that as well.
Solution
Correct the wrong parts of the specification, using the specified "following code" behavior uniformly, which is already the long-standing implementation behavior.
Also note value
can be null, and clarify the CCE conditions.
Specification
--- a/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java
+++ b/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java
@@ -369,17 +369,32 @@ public static VarHandle arrayVarHandle(MethodHandles.Lookup lookup, String name,
* <p>
* Otherwise one of the following conversions is applied to {@code value}:
* <ol>
- * <li>If {@code dstType} is a reference type, a reference cast
- * is applied to {@code value} as if by calling {@code dstType.cast(value)}.
- * <li>If {@code dstType} is a primitive type, then, if the runtime type
- * of {@code value} is a primitive wrapper type (such as {@link Integer}),
- * a Java unboxing conversion is applied {@jls 5.1.8} followed by a
- * Java casting conversion {@jls 5.5} converting either directly to
- * {@code dstType}, or, if {@code dstType} is {@code boolean},
- * to {@code int}, which is then converted to either {@code true}
- * or {@code false} depending on whether the least-significant-bit
- * is 1 or 0 respectively. If the runtime type of {@code value} is
- * not a primitive wrapper type a {@link ClassCastException} is thrown.
+ * <li>If {@code dstType} is a reference type, a reference cast is applied
+ * to {@code value} as if by calling {@link Class#cast(Object)
+ * dstType.cast(value)}.
+ * <li>Otherwise, {@code dstType} is a primitive type:
+ * <ol>
+ * <li>If {@code value} is null, the default value (JVMS {@jvms 2.3})
+ * of {@code dstType} is returned.
+ * <li>If the runtime type of {@code value} is a primitive wrapper type
+ * (such as {@link Integer}), a Java unboxing conversion is applied
+ * (JLS {@jls 5.1.8}).
+ * <ul>
+ * <li>If the runtime type is {@link Boolean}, the unboxing result
+ * is then converted to {@code int}, where {@code true} becomes
+ * {@code 1} and {@code false} becomes {@code 0}.
+ * </ul>
+ * Followed by a Java casting conversion (JLS {@jls 5.5}):
+ * <ul>
+ * <li>If {@code dstType} is not {@code boolean}, the cast converts
+ * directly to {@code dstType}.
+ * <li>If {@code dstType} is {@code boolean}, the cast converts to
+ * {@code int}, and the resulting {@code boolean} is produced
+ * by testing whether the least significant bit of the cast
+ * {@code int} is 1.
+ * </ul>
+ * <li>Otherwise, a {@link ClassCastException} is thrown.
+ * </ol>
* </ol>
* <p>
* The result is the same as when using the following code:
@@ -393,13 +408,10 @@ public static VarHandle arrayVarHandle(MethodHandles.Lookup lookup, String name,
* @param lookup unused
* @param name unused
* @param dstType the destination type of the conversion
- * @param value the value to be converted
+ * @param value the value to be converted, may be null
* @return the converted value
- * @throws ClassCastException when {@code dstType} is {@code void},
- * when a cast per (1) fails, or when {@code dstType} is a primitive type
- * and the runtime type of {@code value} is not a primitive wrapper type
- * (such as {@link Integer})
- *
+ * @throws ClassCastException when {@code dstType} is {@code void}; when
+ * {@code dstType} is a reference type, and the reference cast fails; or
+ * when {@code dstType} is primitive, and {@code value} is an
+ * instance of a reference type that is not a wrapper class
* @since 15
*/
public static Object explicitCast(MethodHandles.Lookup lookup, String name, Class<?> dstType, Object value)
- csr of
-
JDK-8364751 ConstantBootstraps.explicitCast contradictory specification for null-to-primitive
-
- Resolved
-