From 5e3f13d739836909f7632eb0e39046edd6c16476 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Sat, 9 Aug 2025 17:31:30 -0700 Subject: [PATCH 1/2] 8364751: ConstantBootstraps.explicitCast violates doc contracts for null-to-int --- .../java/lang/invoke/ConstantBootstraps.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java b/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java index b7983d18b2e5c..c377d2ecdba07 100644 --- a/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java +++ b/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -373,13 +373,14 @@ public static VarHandle arrayVarHandle(MethodHandles.Lookup lookup, String name, * is applied to {@code value} as if by calling {@code dstType.cast(value)}. *
  • 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 + * a Java unboxing conversion is applied (JLS {@jls 5.1.8}) followed by a + * Java casting conversion (JLS {@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. + * is 1 or 0 respectively. If {@code value} is null, the zero value for + * the {@code dstType} is returned. Otherwise, a {@link ClassCastException} + * is thrown. * *

    * The result is the same as when using the following code: @@ -397,8 +398,8 @@ public static VarHandle arrayVarHandle(MethodHandles.Lookup lookup, String name, * @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}) + * and {@code value} is not null and its runtime type is not a primitive + * wrapper type (such as {@link Integer}) * * @since 15 */ From 3f69079bf77cbfbe5655ca4f273796269fd505b2 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Sat, 9 Aug 2025 17:54:32 -0700 Subject: [PATCH 2/2] Update and consolidate tests --- test/jdk/java/lang/constant/ConvertTest.java | 79 ------------------- .../invoke/condy/ConstantBootstrapsTest.java | 46 ++++++++++- 2 files changed, 44 insertions(+), 81 deletions(-) delete mode 100644 test/jdk/java/lang/constant/ConvertTest.java diff --git a/test/jdk/java/lang/constant/ConvertTest.java b/test/jdk/java/lang/constant/ConvertTest.java deleted file mode 100644 index d7018df635291..0000000000000 --- a/test/jdk/java/lang/constant/ConvertTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @run testng ConvertTest - */ - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import java.lang.invoke.ConstantBootstraps; -import java.math.BigInteger; - -import static org.testng.Assert.assertEquals; - -public class ConvertTest { - - @DataProvider - public static Object[][] cceInputs() { - return new Object[][]{ - { void.class, null }, - { Integer.class, "a" }, - { int.class, BigInteger.ZERO }, - }; - } - - @Test(dataProvider = "cceInputs", expectedExceptions = ClassCastException.class) - public void testBadConversion(Class dstType, Object value) { - ConstantBootstraps.explicitCast(null, null, dstType, value); - } - - @DataProvider - public static Object[][] goodInputs() { - Object o = new Object(); - return new Object[][]{ - { Object.class, null, null }, - { Object.class, o, o }, - { String.class, "abc", "abc" }, - { short.class, 10, (short) 10 }, - { int.class, (short) 10, 10 }, - { boolean.class, 1, true }, - { boolean.class, 2, false }, - { int.class, true, 1 }, - { int.class, false, 0 }, - { int.class, 10, 10 }, - { Integer.class, 10, 10 }, - { Object.class, 10, 10 }, - { Number.class, 10, 10 }, - }; - } - - @Test(dataProvider = "goodInputs") - public void testSuccess(Class dstType, Object value, Object expected) { - Object actual = ConstantBootstraps.explicitCast(null, null, dstType, value); - assertEquals(actual, expected); - } - -} diff --git a/test/jdk/java/lang/invoke/condy/ConstantBootstrapsTest.java b/test/jdk/java/lang/invoke/condy/ConstantBootstrapsTest.java index 640affeec5c3c..829f26704f943 100644 --- a/test/jdk/java/lang/invoke/condy/ConstantBootstrapsTest.java +++ b/test/jdk/java/lang/invoke/condy/ConstantBootstrapsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8186046 8195694 + * @bug 8186046 8195694 8241100 8364751 * @summary Test dynamic constant bootstraps * @library /java/lang/invoke/common * @build test.java.lang.invoke.lib.InstructionHelper @@ -31,6 +31,7 @@ * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 ConstantBootstrapsTest */ +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import test.java.lang.invoke.lib.InstructionHelper; @@ -241,4 +242,45 @@ public void testVarHandleArray() throws Throwable { assertEquals(vhandle.varType(), String.class); assertEquals(vhandle.coordinateTypes(), List.of(String[].class, int.class)); } + + @DataProvider + public static Object[][] cceCasts() { + return new Object[][]{ + { void.class, null }, + { Integer.class, "a" }, + { int.class, BigInteger.ZERO }, + }; + } + + @Test(dataProvider = "cceCasts", expectedExceptions = ClassCastException.class) + public void testBadCasts(Class dstType, Object value) { + ConstantBootstraps.explicitCast(null, null, dstType, value); + } + + @DataProvider + public static Object[][] validCasts() { + Object o = new Object(); + return new Object[][]{ + { Object.class, null, null }, + { Object.class, o, o }, + { String.class, "abc", "abc" }, + { short.class, 10, (short) 10 }, + { int.class, (short) 10, 10 }, + { boolean.class, 1, true }, + { boolean.class, 2, false }, + { int.class, true, 1 }, + { int.class, false, 0 }, + { int.class, 10, 10 }, + { Integer.class, 10, 10 }, + { Object.class, 10, 10 }, + { Number.class, 10, 10 }, + { char.class, null, (char) 0 } + }; + } + + @Test(dataProvider = "validCasts") + public void testSuccessfulCasts(Class dstType, Object value, Object expected) { + Object actual = ConstantBootstraps.explicitCast(null, null, dstType, value); + assertEquals(actual, expected); + } }