diff --git a/src/java.base/share/classes/jdk/internal/reflect/DirectConstructorHandleAccessor.java b/src/java.base/share/classes/jdk/internal/reflect/DirectConstructorHandleAccessor.java index 4c0f7bdabb0..03a327b9e2c 100644 --- a/src/java.base/share/classes/jdk/internal/reflect/DirectConstructorHandleAccessor.java +++ b/src/java.base/share/classes/jdk/internal/reflect/DirectConstructorHandleAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, 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 @@ -44,23 +44,18 @@ class DirectConstructorHandleAccessor extends ConstructorAccessorImpl { return new NativeAccessor(ctor); } - private static final int PARAM_COUNT_MASK = 0x00FF; - private static final int NONZERO_BIT = 0x8000_0000; - - private final int paramFlags; + private final int paramCount; private final MethodHandle target; DirectConstructorHandleAccessor(Constructor ctor, MethodHandle target) { - this.paramFlags = (ctor.getParameterCount() & PARAM_COUNT_MASK) | NONZERO_BIT; + this.paramCount = ctor.getParameterCount(); this.target = target; } @Override public Object newInstance(Object[] args) throws InstantiationException, InvocationTargetException { int argc = args != null ? args.length : 0; - // only check argument count for specialized forms - int paramCount = paramFlags & PARAM_COUNT_MASK; - if (paramCount <= SPECIALIZED_PARAM_COUNT && argc != paramCount) { + if (argc != paramCount) { throw new IllegalArgumentException("wrong number of arguments: " + argc + " expected: " + paramCount); } try { @@ -87,7 +82,7 @@ class DirectConstructorHandleAccessor extends ConstructorAccessorImpl { @Hidden @ForceInline Object invokeImpl(Object[] args) throws Throwable { - return switch (paramFlags & PARAM_COUNT_MASK) { + return switch (paramCount) { case 0 -> target.invokeExact(); case 1 -> target.invokeExact(args[0]); case 2 -> target.invokeExact(args[0], args[1]); diff --git a/src/java.base/share/classes/jdk/internal/reflect/DirectMethodHandleAccessor.java b/src/java.base/share/classes/jdk/internal/reflect/DirectMethodHandleAccessor.java index 86609cc2727..942d0cfa4f8 100644 --- a/src/java.base/share/classes/jdk/internal/reflect/DirectMethodHandleAccessor.java +++ b/src/java.base/share/classes/jdk/internal/reflect/DirectMethodHandleAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, 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 @@ -39,7 +39,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import static java.lang.invoke.MethodType.genericMethodType; -import static jdk.internal.reflect.MethodHandleAccessorFactory.SPECIALIZED_PARAM_COUNT; import static jdk.internal.reflect.MethodHandleAccessorFactory.LazyStaticHolder.JLIA; class DirectMethodHandleAccessor extends MethodAccessorImpl { @@ -329,9 +328,6 @@ class DirectMethodHandleAccessor extends MethodAccessorImpl { } private static void checkArgumentCount(int paramCount, Object[] args) { - // only check argument count for specialized forms - if (paramCount > SPECIALIZED_PARAM_COUNT) return; - int argc = args != null ? args.length : 0; if (argc != paramCount) { throw new IllegalArgumentException("wrong number of arguments: " + argc + " expected: " + paramCount); diff --git a/test/jdk/java/lang/reflect/MethodHandleAccessorsTest.java b/test/jdk/java/lang/reflect/MethodHandleAccessorsTest.java index 1636bd70445..17e9be0cf45 100644 --- a/test/jdk/java/lang/reflect/MethodHandleAccessorsTest.java +++ b/test/jdk/java/lang/reflect/MethodHandleAccessorsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, 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 8271820 + * @bug 8271820 8300924 * @modules java.base/jdk.internal.reflect * @summary Test compliance of ConstructorAccessor, FieldAccessor, MethodAccessor implementations * @run testng/othervm --add-exports java.base/jdk.internal.reflect=ALL-UNNAMED -Djdk.reflect.useDirectMethodHandle=true -XX:-ShowCodeDetailsInExceptionMessages MethodHandleAccessorsTest @@ -55,6 +55,8 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class MethodHandleAccessorsTest { + static final boolean newImpl = Boolean.getBoolean("jdk.reflect.useDirectMethodHandle"); + public static void public_static_V() {} @@ -68,6 +70,12 @@ public class MethodHandleAccessorsTest { public static int public_static_I_I(int i) { return i; } + public static void public_static_V_L3(Object o1, Object o2, Object o3) { } + + public static void public_static_V_L4(Object o1, Object o2, Object o3, Object o4) { } + + public static void public_V_L5(Object o1, Object o2, Object o3, Object o4, Object o5) { } + public void public_I_V(int i) {} public int public_I_I(int i) { return i; } @@ -146,6 +154,14 @@ public class MethodHandleAccessorsTest { this(varargs_object(first, rest)); } + public Public(Object o1, Object o2, Object o3) { + this("3-arg constructor"); + } + + public Public(Object o1, Object o2, Object o3, Object o4) { + this("4-arg constructor"); + } + public Public(RuntimeException exc) { throw exc; } @@ -405,6 +421,10 @@ public class MethodHandleAccessorsTest { private static final Throwable[] wrong_argument_count_no_details = new Throwable[] { new IllegalArgumentException("wrong number of arguments") }; + + private static final Throwable[] wrong_argument_count_zero_args = new Throwable[] { + new IllegalArgumentException("wrong number of arguments: 0 expected:") + }; private static final Throwable[] wrong_argument_count = new Throwable[] { new IllegalArgumentException("wrong number of arguments"), new IllegalArgumentException("array is not of length 1") @@ -462,7 +482,6 @@ public class MethodHandleAccessorsTest { private Object[][] testOneArgMethods() { MethodHandleAccessorsTest inst = new MethodHandleAccessorsTest(); Object wrongInst = new Object(); - boolean newImpl = Boolean.getBoolean("jdk.reflect.useDirectMethodHandle"); return new Object[][]{ new Object[] {"public_static_I_V", int.class, null, new Object[]{12}, null, noException}, new Object[] {"public_static_I_I", int.class, null, new Object[]{12}, 12, noException}, @@ -493,6 +512,27 @@ public class MethodHandleAccessorsTest { }; } + @DataProvider(name = "testMultiArgMethods") + private Object[][] testMultiArgMethods() { + MethodHandleAccessorsTest inst = new MethodHandleAccessorsTest(); + Class[] params_L3 = new Class[] { Object.class, Object.class, Object.class}; + Class[] params_L4 = new Class[] { Object.class, Object.class, Object.class, Object.class}; + Class[] params_L5 = new Class[] { Object.class, Object.class, Object.class, Object.class, Object.class}; + + return new Object[][]{ + new Object[]{"public_static_V_L3", params_L3, null, new Object[3], null, noException}, + new Object[]{"public_static_V_L4", params_L4, null, new Object[4], null, noException}, + new Object[]{"public_V_L5", params_L5, inst, new Object[5], null, noException}, + // wrong arguments + new Object[]{"public_static_V_L3", params_L3, null, null, null, + newImpl ? wrong_argument_count_zero_args : wrong_argument_count_no_details}, + new Object[]{"public_static_V_L4", params_L4, null, new Object[0], null, + newImpl ? wrong_argument_count_zero_args : wrong_argument_count_no_details}, + new Object[]{"public_V_L5", params_L5, inst, null, null, + newImpl ? wrong_argument_count_zero_args : wrong_argument_count_no_details}, + }; + } + @DataProvider(name = "testMethodsWithVarargs") private Object[][] testMethodsWithVarargs() { Class[] paramTypes = new Class[] { int[].class }; @@ -523,6 +563,12 @@ public class MethodHandleAccessorsTest { doTest(MethodHandleAccessorsTest.class.getDeclaredMethod(methodname, paramType), target, args, expectedReturn, expectedExpections); } + @Test(dataProvider = "testMultiArgMethods") + public void testMultiArgMethod(String methodname, Class[] paramTypes, Object target, Object[] args, + Object expectedReturn, Throwable[] expectedExpections) throws Exception { + doTest(MethodHandleAccessorsTest.class.getDeclaredMethod(methodname, paramTypes), target, args, expectedReturn, expectedExpections); + } + @Test(dataProvider = "testMethodsWithVarargs") public void testMethodsWithVarargs(String methodname, Class[] paramTypes, Object target, Object[] args, Object expectedReturn, Throwable[] expectedExpections) throws Exception { @@ -561,6 +607,26 @@ public class MethodHandleAccessorsTest { doTest(Public.class.getDeclaredConstructor(paramTypes), args, expectedReturn, expectedExpections); } + @DataProvider(name = "testMultiArgConstructors") + private Object[][] testMultiArgConstructors() { + Class[] params_L3 = new Class[] { Object.class, Object.class, Object.class}; + Class[] params_L4 = new Class[] { Object.class, Object.class, Object.class, Object.class}; + Object o = "arg"; + return new Object[][]{ + new Object[]{params_L3, new Object[3], new Public(o, o, o), noException}, + new Object[]{params_L4, new Object[4], new Public(o, o, o, o), noException}, + new Object[]{params_L3, new Object[]{}, null, + newImpl ? wrong_argument_count_zero_args : wrong_argument_count_no_details}, + new Object[]{params_L4, null, null, + newImpl ? wrong_argument_count_zero_args : wrong_argument_count_no_details}, + }; + } + + @Test(dataProvider = "testMultiArgConstructors") + public void testMultiArgConstructors(Class[] paramTypes, Object[] args, Object expectedReturn, Throwable[] expectedExpections) throws Exception { + doTest(Public.class.getDeclaredConstructor(paramTypes), args, expectedReturn, expectedExpections); + } + @Test public void testOtherConstructors() throws Exception { doTest(Private.class.getDeclaredConstructor(), new Object[]{}, new Private());